/**
 @file sys_usw_nexthop.c

 @date 2009-09-16

 @version v2.0

 The file contains all nexthop module core logic
*/

/****************************************************************************
 *
* Header Files
*
****************************************************************************/
#include "ctc_const.h"
#include "ctc_error.h"
#include "ctc_common.h"
#include "ctc_linklist.h"

#include "ctc_packet.h"
#include "ctc_warmboot.h"

#include "sys_usw_common.h"
#include "sys_usw_opf.h"
#include "sys_usw_qos_api.h"
#include "sys_usw_port_api.h"
#include "sys_usw_vlan.h"
#include "sys_usw_l3if.h"
#include "sys_usw_ftm.h"
#include "sys_usw_aps.h"
#include "sys_usw_register.h"
#include "sys_usw_nexthop_api.h"
#include "sys_usw_nexthop_hw.h"
#include "sys_usw_nexthop.h"
#include "sys_usw_wb_nh.h"
#include "sys_usw_wb_common.h"
#include "sys_usw_stats.h"
#include "sys_usw_parser.h"
#include "sys_usw_rpf_spool.h"
#include "sys_usw_internal_port.h"

#include "drv_api.h"
/****************************************************************************
 *
* Defines and Macros
*
*****************************************************************************/


#define DS_ARRAY_T(size) struct { uint32 array[size/4];}
#define SYS_NH_UDF_PROF_NUM     8

/*dsnh_offset When low 0~30bit not zero, the 31bit indicate use igs edit or egs edit mode
1:indicate the nexthop use ingress edit, 0: other dsnh_offset not zero, use egress edit*/
#define SYS_USW_NH_DSNH_OFFSET_IGS_EDIT_BIT  31
#define SYS_USW_NH_DSNH_OFFSET_NO_HW_BIT  30    /*no need write dsnexthop*/
#define SYS_USW_NH_DSNH_OFFSET_MAPPER  29
#define SYS_USW_NH_DSNH_OFFSET_VALID(dsnh_offset)   ((dsnh_offset)&0x3FFFFFFF)



extern sys_usw_nh_api_master_t* p_usw_nh_api_master[CTC_MAX_LOCAL_CHIP_NUM_PP];
extern int32 _sys_usw_cpu_reason_get_info(uint8 lchip, uint16 reason_id, sys_cpu_reason_dest_info_t* p_dest_info);
extern int32 _sys_usw_get_sub_queue_id_by_cpu_reason(uint8 lchip, uint16 reason_id, uint16* sub_queue_id);
extern int32 _sys_usw_nh_update_tunnel_ref_info(uint8 lchip, sys_nh_info_mpls_t* p_nhinfo, uint16 tunnel_id, uint8 is_add);
extern int32 _sys_usw_nh_wb_traverse_sync_mcast(void *data,uint32 vec_index, void *user_data);
extern int32 _sys_usw_nh_wb_restore_mcast(uint8 lchip,  ctc_wb_query_t *p_wb_query);
extern int32 _sys_usw_nh_aps_update_ref_list(uint8 lchip, sys_nh_info_aps_t* p_nhdb, sys_nh_info_com_t* p_nh_info, uint8 is_del);
extern int32 sys_usw_nh_ecmp_add_ref_list(uint8 lchip, sys_nh_info_ecmp_t* p_nhdb, sys_nh_info_com_t* p_nh_info);
int32 _sys_usw_nh_wb_traverse_sync_mcast_mem(void *data,uint32 vec_index, void *user_data);
extern int32 sys_usw_cpu_reason_get_nexthop_info(uint8 lchip, uint16 reason_id, uint32* nexthop_ptr,uint8* dsnh_8w);
extern uint32 sys_usw_nh_get_offset_ref_cnt(uint8 lchip, uint32 offset);

/**********************************/
enum opf_nh_index
{
    OPF_NH_DYN1_SRAM, /*dynamic sram(DsFwd) */
    OPF_NH_DYN2_SRAM, /*dynamic sram(DsEdit) */
    OPF_NH_DYN3_SRAM, /*dynamic sram(DsMet) */
    OPF_NH_DYN4_SRAM, /*dynamic sram(DsNexthop) */
    OPF_NH_DYN5_SRAM, /*dynamic sram(DsFwd1) */
    OPF_NH_DYN6_SRAM, /*dynamic sram(DsEditInner) */
    OPF_NH_NHID_INTERNAL,  /*internal NHID for DsNexthop*/
    OPF_NH_OUTER_L2EDIT,  /*dsl2outeredit for arp*/
    OPF_NH_OUTER_SPME,  /*dsl2outeredit for spme*/
    OPF_NH_L2EDIT_VLAN_PROFILE,  /*vlan action profile for dsl2edit*/
    OPF_NH_DESTMAP_PROFILE, /*arp destmap profile*/
    OPF_NH_FP_ALU_PROFILE, /*fp alu profile*/
    OPF_NH_FP_DATA_PROFILE, /*fp data profile*/
    OPF_NH_FP_L3CHKSUM_PROFILE, /*fp l3chksum profile*/
    OPF_NH_FP_L4CHKSUM_PROFILE, /*fp l4chksumprofile*/
    OPF_NH_XFP_EDIT, /* AT, fp forXEdit*/
    OPF_NH_XFP_ALU_PROFILE, /* AT, fp alu profile for XEdit*/
    OPF_NH_XFP_DATA_PROFILE, /* AT, fp data profile for XEdit*/
    OPF_NH_LOGIC_REP, /*logic repli list*/
    OPF_NH_LOGIC_PORT,
    OPF_NH_LDP_MAC_PROFILE, /*logic port mac profile*/
    OPF_NH_LOGIC_PORT_EXT,

    OPF_NH_DYN_MAX
};

#define SYS_USW_INVALID_STATS_PTR 0
#define SYS_USW_NH_DROP_DESTMAP          0xFFFE


#define SYS_NH_EXTERNAL_NHID_DEFAUL_NUM 0x80000000
#define SYS_NH_TUNNEL_ID_DEFAUL_NUM     1024

#define SYS_NH_ARP_ID_DEFAUL_NUM        64*1024
#define SYS_NH_SRH_ID_DEFAUL_NUM        4096

#define SYS_NH_MCAST_LOGIC_MAX_CNT       32
#define SYS_NH_MAX_VXLAN_PROFLLE       (MCHIP_CAP(SYS_CAP_NH_VXLAN_PROFLLE_NUM))

#define SYS_NH_DB_TYPE_NH_INFO     1
#define SYS_NH_DB_TYPE_NH_INFO_EXT 2
#define SYS_NH_DB_TYPE_MPLS_TNL    3
#define SYS_NH_DB_TYPE_SRH         4
#define SYS_NH_DB_TYPE_ARP         5
#define SYS_NH_DB_TYPE_OVERLAY_TNL 6


#define SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(_dsnh)    \
    do {                                                      \
       _dsnh.replace_ctag_cos = 0;\
       _dsnh.copy_ctag_cos= 0;    \
       _dsnh.derive_stag_cos= 1;\
       _dsnh.stag_cfi= 0;\
    } while (0)

#define SYS_USW_NH_DSNH_ASSIGN_MACDA(_dsnh, _dsnh_param)         \
    do {                                                               \
         sal_memcpy(_dsnh.mac_da, _dsnh_param.macDa, sizeof(mac_addr_t)); \
    } while (0)

#define SYS_USW_NH_DSNH_BUILD_L2EDITPTR_L3EDITPTR(__dsnh,     \
                                                        __dsnh_l2editptr, __dsnh_l3editptr)     \
    do {                                                            \
    } while (0)

#define SYS_USW_NH_DSNH8W_BUILD_L2EDITPTR_L3EDITPTR(__dsnh,   \
                                                          __dsnh_l2editptr, __dsnh_l3editptr)     \
    do {                                                            \
    } while (0)

#define SYS_USW_NH_DSNH_BUILD_FLAG(__dsnh,  flag)  \
    do {                                                                    \
        if (CTC_FLAG_ISSET(flag, SYS_NH_PARAM_FLAG_USE_TTL_FROM_PKT)) \
        { \
            __dsnh.use_packet_ttl = 1;\
        } \
        if (CTC_FLAG_ISSET(flag, SYS_NH_PARAM_FLAG_USE_MAPPED_STAG_COS)) \
        { \
            __dsnh.stag_cfi = 1; \
        } \
        if (CTC_FLAG_ISSET(flag, SYS_NH_PARAM_FLAG_USE_MAPPED_CTAG_COS)) \
        { \
            __dsnh.replace_ctag_cos = 1; \
        } \
        if (CTC_FLAG_ISSET(flag, SYS_NH_PARAM_FLAG_USE_MAPPED_DSCP)) \
        { \
            __dsnh.map_dscp = 1; \
        } \
        else if (CTC_FLAG_ISSET(flag, SYS_NH_PARAM_FLAG_USE_COPY_DSCP)) \
        { \
            __dsnh.copy_dscp = 1; \
        } \
    } while (0)

#define SYS_USW_NH_MAX_ECMP_CHECK(max_ecmp)  \
    do {    \
        if ((max_ecmp%4 != 0) || (max_ecmp > 0 && max_ecmp < 16))    \
        {   \
            return CTC_E_INVALID_PARAM; \
        }   \
        else if (max_ecmp > MCHIP_CAP(SYS_CAP_NH_MAX_ECPN))   \
        {   \
            return CTC_E_INVALID_PARAM;    \
        }   \
    } while (0)

/****************************************************************************
 *
* Global and Declaration
*
*****************************************************************************/

sys_usw_nh_master_t* g_usw_nh_master[CTC_MAX_LOCAL_CHIP_NUM_PP] = { NULL };



/****************************************************************************
 *
* Function
*
*****************************************************************************/
int32
sys_usw_nh_get_nhinfo_by_nhid(uint8 lchip, uint32 nhid, sys_nh_info_com_t** pp_nhinfo);


int32
_sys_usw_nh_alloc_offset_by_nhtype(uint8 lchip, sys_nh_param_com_t* p_nh_com_para, sys_nh_info_com_t* p_nhinfo);



int32
_sys_usw_nh_free_offset_by_nhinfo(uint8 lchip, sys_usw_nh_type_t nh_type, sys_nh_info_com_t* p_nhinfo);

extern int32
_sys_usw_nh_ipuc_update_dsnh_cb(uint8 lchip, sys_nh_db_arp_t* p_arp_db, uint32 nh_id);

#define __________db__________

int32
_sys_usw_nh_get_nh_resource(uint8 lchip, uint32 type, uint32* used_count)
{
    uint32 index_end = 0;
    uint32 index_start = 0;
    uint32 index = 0;
    uint32 num = 0;

    switch(type)
    {
        case SYS_NH_ENTRY_TYPE_L2EDIT_FROM:
            index_start = SYS_NH_ENTRY_TYPE_L2EDIT_FROM;
            index_end = SYS_NH_ENTRY_TYPE_L2EDIT_TO;
            break;
        case SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W:
            index_start = SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W;
            index_end = SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W;
            break;
        case SYS_NH_ENTRY_TYPE_L3EDIT_FROM:
            index_start = SYS_NH_ENTRY_TYPE_L3EDIT_FROM;
            index_end = SYS_NH_ENTRY_TYPE_L3EDIT_TO;
            break;
        case SYS_NH_ENTRY_TYPE_MET:
            index_start = SYS_NH_ENTRY_TYPE_MET;
            index_end = SYS_NH_ENTRY_TYPE_MET_12W;
            break;
        case SYS_NH_ENTRY_TYPE_NEXTHOP_4W:
            index_start = SYS_NH_ENTRY_TYPE_NEXTHOP_4W;
            index_end = SYS_NH_ENTRY_TYPE_NEXTHOP_8W;
            break;
        case SYS_NH_ENTRY_TYPE_FWD:
            index_start = SYS_NH_ENTRY_TYPE_FWD;
            index_end = SYS_NH_ENTRY_TYPE_FWD_HALF;
            break;
        case SYS_NH_ENTRY_TYPE_FWD1:
            index_start = SYS_NH_ENTRY_TYPE_FWD1;
            index_end = SYS_NH_ENTRY_TYPE_FWD_HALF1;
            break;

        case SYS_NH_ENTRY_TYPE_L2EDIT_INNER_FROM:
            index_start = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_FROM;
            index_end = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_TO;
            break;
        case SYS_NH_ENTRY_TYPE_L3EDIT_INNER_FROM:
            index_start = SYS_NH_ENTRY_TYPE_L3EDIT_INNER_FROM;
            index_end = SYS_NH_ENTRY_TYPE_L3EDIT_INNER_TO;
            break;
         default:
            index_start = type;
            index_end = type;
    }

    for(index = index_start; index <= index_end; index++)
    {
        num += g_usw_nh_master[lchip]->nhtbl_used_cnt[index];
    }

    if(type == SYS_NH_ENTRY_TYPE_MET)
    {
        num += g_usw_nh_master[lchip]->max_glb_met_offset;
    }
    else if(type == SYS_NH_ENTRY_TYPE_NEXTHOP_4W)
    {
        num += g_usw_nh_master[lchip]->max_glb_nh_offset;
    }

    *used_count = num;

    return CTC_E_NONE;
}

/**
 @brief This function is used to get nexthop module master data
 */
bool
_sys_usw_nh_is_ipmc_logic_rep_enable(uint8 lchip)
{
    return g_usw_nh_master[lchip]->ipmc_logic_replication ? TRUE : FALSE;
}




int32
_sys_usw_nh_set_ipmc_logic_replication(uint8 lchip, uint8 enable)
{
    if (DRV_FROM_TMM(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER, 1);
    g_usw_nh_master[lchip]->ipmc_logic_replication  = (enable) ? 1 : 0;

    return CTC_E_NONE;
}

int32
sys_usw_nh_get_arp_oif(uint8 lchip, uint32 arp_id, ctc_nh_oif_info_t *p_oif, uint8* p_mac, uint8* is_drop, uint16* l3if_id)
{
    sys_nh_db_arp_t*  p_arp = NULL;
    if (0 != arp_id)
    {
        p_arp = sys_usw_nh_lkup_arp_id(lchip, arp_id);
        if (!p_arp)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not found \n");
			return CTC_E_NOT_EXIST;

        }

        if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_VLAN_VALID))
        {
            p_oif->vid = p_arp->output_vid;
        }

        if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_CVLAN_VALID))
        {
            p_oif->cvid = p_arp->output_cvid;
        }

        if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_PORT_VALID))
        {
            p_oif->gport = p_arp->gport;
            if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU))
            {
                p_oif->gport = CTC_GPORT_RCPU((CTC_MAP_GPORT_TO_GCHIP(p_arp->gport)));
            }
        }
        if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_L3IF_VALID) && l3if_id && (0xff != p_oif->rsv[0]))
        {
            *l3if_id = p_arp->l3if_id;
        }

        if (is_drop)
        {
            *is_drop = CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_DROP)?1:0;
        }

        if (p_mac)
        {
            sal_memcpy(p_mac, p_arp->mac_da, sizeof(mac_addr_t));
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_write_entry_arp(uint8 lchip, sys_nh_db_arp_t* p_ds_arp)
{
    uint32 cmd                     = 0;
    uint32 lport                   = 0;
    uint8 dest_gchip               = 0;
    uint32 dest_map                = 0;
    uint8 is_drop = CTC_FLAG_ISSET(p_ds_arp->flag, SYS_NH_ARP_FLAG_DROP)?1:0;
    sys_dsl2edit_eth_t   dsl2edit_4w;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_PARAM, "Arp_Id:%u, DestMapProfile:%u\n", p_ds_arp->arp_id, p_ds_arp->destmap_profile);

    if (CTC_FLAG_ISSET(p_ds_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU))
    {
        /*Exception to cpu, special for arp to cpu reason*/
        dest_map = 0xFFFF;

    }
    else if(CTC_FLAG_ISSET(p_ds_arp->flag, SYS_NH_ARP_FLAG_DROP) && p_ds_arp->destmap_profile)
    {
        lport = SYS_RSV_PORT_DROP_ID;
        sys_usw_get_gchip_id(lchip, &dest_gchip);

        if (CTC_FLAG_ISSET(p_ds_arp->flag, SYS_NH_ARP_PORT_VALID))
        {
            p_ds_arp->gport = SYS_MAP_DRV_LPORT_TO_CTC_GPORT(dest_gchip, lport);
            dest_map = SYS_ENCODE_DESTMAP(dest_gchip, SYS_RSV_PORT_DROP_ID);
        }
    }
    else
    {
        /*Set the output port*/
        if (!is_drop)
        {
            lport = CTC_MAP_GPORT_TO_LPORT(p_ds_arp->gport);
            dest_gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_ds_arp->gport);
            dest_map = SYS_ENCODE_DESTMAP(dest_gchip, lport);
        }
    }

    sal_memset(&dsl2edit_4w, 0, sizeof(dsl2edit_4w));
    sal_memcpy(dsl2edit_4w.mac_da, p_ds_arp->mac_da, sizeof(mac_addr_t));

    dsl2edit_4w.ds_type  = is_drop?SYS_NH_DS_TYPE_DISCARD:SYS_NH_DS_TYPE_L2EDIT;
    if (DRV_IS_DUET2(lchip) || DRV_IS_TSINGMA(lchip))
    {
        dsl2edit_4w.l2_rewrite_type  = p_ds_arp->is_8w? SYS_NH_L2EDIT_TYPE_ETH_8W : SYS_NH_L2EDIT_TYPE_ETH_4W;
    }
    else
    {
        dsl2edit_4w.l2_rewrite_type  = p_ds_arp->is_8w? DRV_ENUM(DRV_L2EDITTYPE_ADDETH2X) : DRV_ENUM(DRV_L2EDITTYPE_ADDETH1X);
    }
    dsl2edit_4w.output_vid= p_ds_arp->output_vid;
    dsl2edit_4w.output_cvid = p_ds_arp->output_cvid;
    dsl2edit_4w.output_vid_valid = CTC_FLAG_ISSET(p_ds_arp->flag, SYS_NH_ARP_VLAN_VALID)?1:0;
    dsl2edit_4w.output_cvid_valid = CTC_FLAG_ISSET(p_ds_arp->flag, SYS_NH_ARP_CVLAN_VALID)?1:0;
    dsl2edit_4w.is_8w = p_ds_arp->is_8w;

    /*write outer static l2edit*/
    if (p_ds_arp->offset)
    {
        dsl2edit_4w.offset = p_ds_arp->offset;/*for write 4w*/
        CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, p_ds_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W : SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, p_ds_arp->offset, &dsl2edit_4w));
    }

    /*write dynamic l2edit*/
    if (p_ds_arp->offset_dyn)
    {
        CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, p_ds_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, p_ds_arp->offset_dyn, &dsl2edit_4w));
    }


    /*write mac profile(share the port mac)*/
    if (p_ds_arp->ldp_mac_profile)
    {
        sys_usw_port_api_set_port_mac(lchip, p_ds_arp->ldp_mac_profile, p_ds_arp->mac_da);
    }


    if (p_ds_arp->destmap_profile)
    {
        ds_t ds;
        cmd = DRV_IOR(DsDestMapProfileUc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_ds_arp->destmap_profile, cmd, &ds));
        SetDsDestMapProfileUc(V, destMap_f, &ds, dest_map);
        cmd = DRV_IOW(DsDestMapProfileUc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_ds_arp->destmap_profile, cmd, &ds));

        cmd = DRV_IOR(DsDestMapProfileUc1_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_ds_arp->destmap_profile, cmd, &ds));
        SetDsDestMapProfileUc1(V, destMap_f, &ds, dest_map);
        cmd = DRV_IOW(DsDestMapProfileUc1_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_ds_arp->destmap_profile, cmd, &ds));

        cmd = DRV_IOR(DsDestMapProfileMc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_ds_arp->destmap_profile, cmd, &ds));
        SetDsDestMapProfileMc(V, destMap_f, &ds, dest_map);
        SetDsDestMapProfileMc(V, copyDestMapBit18_f, &ds, 1);
        cmd = DRV_IOW(DsDestMapProfileMc_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_ds_arp->destmap_profile, cmd, &ds));
    }

    return CTC_E_NONE;

}

#define NH_L2EDIT

int32
sys_usw_nh_add_l2edit(uint8 lchip, sys_dsl2edit_eth_t* p_dsl2edit_eth, uint8 edit_type, uint32* p_offset)  /*output sys_nh_db_edit_t*/
{
    int32 ret = CTC_E_NONE;
    sys_nh_db_edit_t* p_db_out = NULL;
    sys_nh_db_edit_t edit_db;
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];
    ds0_t ds;
    ds0_t ds1;
    void *p_ds = NULL;

    /*1. rebuild p_dsl2edit_eth */
     p_dsl2edit_eth->ds_type  = SYS_NH_DS_TYPE_L2EDIT;
    if ((SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W == edit_type)
        ||(SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W == edit_type)
        ||(SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W_RW == edit_type)
        || ((SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W + SYS_NH_TYPE_STEP_TO_INNER) == edit_type)
        || ((SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W_RW + SYS_NH_TYPE_STEP_TO_INNER) == edit_type))
    {
        p_dsl2edit_eth->is_8w = 1;
    }
    p_dsl2edit_eth->l2_rewrite_type = p_master->rewrite_type[edit_type];

    /*2. map to hw ds*/
    sal_memset(ds, 0, sizeof(ds));/*must memset for spool*/
    p_ds = (void*)ds;
    if (p_master->nh_table_info_array[edit_type].p_func)
    {
        CTC_ERROR_RETURN((*p_master->nh_table_info_array[edit_type].p_func)(lchip, (void*)p_dsl2edit_eth, &ds, p_offset));
    }

     /*3. map to hw ds*/
    edit_db.edit_type = edit_type;
    edit_db.offset = 0;
    edit_db.ds = &ds;
    edit_db.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_add(p_master->p_edit_spool, &edit_db, NULL, &p_db_out));

    if (SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W == edit_type)
    {
        uint32 len = DRV_TABLE_ENTRY_SIZE(lchip, DsL2Edit6WOuter_t) / 2;
        CTC_ERROR_DUMP(sys_usw_nh_get_asic_table(lchip, edit_type, p_db_out->offset, &ds1));
        if (p_db_out->offset % 2 == 0)
        {
            sal_memcpy((uint8*)&ds1, &ds, len);
        }
        else
        {
            sal_memcpy((uint8*)&ds1 + len, &ds, len);
        }
        p_ds = (void*)ds1;
    }

    /*4. set to hw*/
    ret = sys_usw_nh_set_asic_table(lchip, edit_type, p_db_out->offset, p_ds);
    if (ret != CTC_E_NONE)
    {
        goto error1;
    }

    *p_offset = p_db_out->offset;

    return CTC_E_NONE;

error1:
    ctc_spool_remove(p_master->p_edit_spool, &edit_db, NULL);
    return ret;
}

int32
sys_usw_nh_remove_l2edit(uint8 lchip, uint8 edit_type, uint32 offset)
{
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];
    sys_nh_db_edit_t edit_db;
    ds0_t ds;

    sal_memset(ds, 0, sizeof(ds));
    CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, edit_type, offset, &ds));
    if (SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W == edit_type)
    {
        uint32 len = DRV_TABLE_ENTRY_SIZE(lchip, DsL2Edit6WOuter_t) / 2;
        if (CTC_IS_BIT_SET(offset, 0))
        {
            sal_memcpy((uint8*)&ds, (uint8*)&ds + len, len);
        }
        sal_memset((uint8*)&ds + len, 0, len);
    }
    edit_db.edit_type = edit_type;
    edit_db.offset = offset;
    edit_db.ds = &ds;
    edit_db.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_remove(p_master->p_edit_spool, &edit_db, NULL));

    return CTC_E_NONE;
}

/*
nhid 0 for alloc reback l2edit ptr
*/
int32
sys_usw_nh_add_loopback_l2edit(uint8 lchip, uint32 nhid, uint8 lb_with_ldp, uint8 is_l2edit, uint32* p_edit_ptr)
{
    ctc_slistnode_t* slist_node = NULL;
    sys_nh_eloop_node_t *p_eloop_node = NULL;
    int32 ret = CTC_E_NONE;
    uint32 new_offset = 0;
    sys_dsl2edit_t l2edit_param;
    sys_nh_info_dsnh_t nhinfo;
    sys_nh_info_com_t* p_nh_com_info;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    sal_memset(&l2edit_param, 0, sizeof(sys_dsl2edit_t));
    sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_LOOP_NH, 1);

    CTC_SLIST_LOOP(g_usw_nh_master[lchip]->eloop_list, slist_node)
    {
        p_eloop_node = _ctc_container_of(slist_node, sys_nh_eloop_node_t, head);
        if ((p_eloop_node->nhid == nhid) && (lb_with_ldp == p_eloop_node->lb_with_ldp))
        {
            *p_edit_ptr = p_eloop_node->edit_ptr;
            p_eloop_node->ref_cnt++;
            return CTC_E_NONE;
        }
    }
    if (nhid)
    {
        CTC_ERROR_RETURN(_sys_usw_nh_get_nhinfo(lchip, nhid, &nhinfo));
    }

     CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, is_l2edit?SYS_NH_ENTRY_TYPE_L2EDIT_LPBK:SYS_NH_ENTRY_TYPE_L3EDIT_LPBK,
                1, &new_offset));


    l2edit_param.ds_type  = nhinfo.drop_pkt ? SYS_NH_DS_TYPE_DISCARD:SYS_NH_DS_TYPE_L2EDIT;
    if(is_l2edit)
    {
       l2edit_param.l2_rewrite_type  =  DRV_FROM_TMM(lchip) ? DRV_ENUM(DRV_L2EDITTYPE_LOOPBACK):SYS_NH_L2EDIT_TYPE_LOOPBACK;
    }
    else
    {
        l2edit_param.l2_rewrite_type  =  DRV_FROM_TMM(lchip) ? DRV_ENUM(DRV_L3EDITTYPE_LOOPBACK):SYS_NH_L3EDIT_TYPE_LOOPBACK;
    }

    l2edit_param.dest_map = nhinfo.dest_map;
    l2edit_param.nexthop_ptr = nhinfo.dsnh_offset;
    l2edit_param.nexthop_ext = nhinfo.nexthop_ext;
    l2edit_param.bypass_igr_edit = nhinfo.bypass_igr_edit;
    if ((SYS_NH_TYPE_ILOOP != nhinfo.nh_entry_type) && DRV_FROM_TMM(lchip))
    {
        l2edit_param.bypass_ipe = 1;
    }
	if (0 == nhid)
    {
        l2edit_param.bypass_ipe = 0;
        l2edit_param.reback = 1;
    }
    l2edit_param.lb_with_ldp = lb_with_ldp;
    CTC_ERROR_GOTO(sys_usw_nh_write_asic_table(lchip,
                                                        is_l2edit?SYS_NH_ENTRY_TYPE_L2EDIT_LPBK: SYS_NH_ENTRY_TYPE_L3EDIT_LPBK,
                                                        new_offset  ,
                                                        &l2edit_param), ret, Error1);

    p_eloop_node =  mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_eloop_node_t));
    if (NULL == p_eloop_node)
    {
        ret = CTC_E_NO_MEMORY;
        goto Error1;
    }
    sal_memset(p_eloop_node, 0, sizeof(sys_nh_eloop_node_t));
    p_eloop_node->nhid = nhid;
    p_eloop_node->edit_ptr = new_offset;
    p_eloop_node->ref_cnt++;
    p_eloop_node->is_l2edit = is_l2edit;
    p_eloop_node->lb_with_ldp = lb_with_ldp;
    if (! ctc_slist_add_tail(g_usw_nh_master[lchip]->eloop_list, &(p_eloop_node->head)))
    {
       ret = CTC_E_NO_MEMORY;
       goto Error1;
    }
    *p_edit_ptr = new_offset;

    if (nhid)
    {
        sys_usw_nh_get_nhinfo_by_nhid(lchip, p_eloop_node->nhid, (sys_nh_info_com_t **)&p_nh_com_info);
        if (p_nh_com_info) CTC_SET_FLAG(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED);
    }
    return CTC_E_NONE;

Error1:
    sys_usw_nh_offset_free(lchip, is_l2edit?SYS_NH_ENTRY_TYPE_L2EDIT_LPBK:SYS_NH_ENTRY_TYPE_L3EDIT_LPBK, 1, new_offset);
    if(p_eloop_node)  mem_free(p_eloop_node);

    return ret;
}

int32
sys_usw_nh_remove_loopback_l2edit(uint8 lchip, uint32 edit_ptr, uint8 is_l2edit)
{
    ctc_slistnode_t* slist_node = NULL;
    ctc_slistnode_t* slist_node2 = NULL;
    sys_nh_eloop_node_t *p_eloop_node = NULL;
    sys_nh_info_com_t* p_nh_com_info;
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_LOOP_NH, 1);
    CTC_SLIST_LOOP_DEL(g_usw_nh_master[lchip]->eloop_list, slist_node, slist_node2)
    {
        p_eloop_node = _ctc_container_of(slist_node, sys_nh_eloop_node_t, head);
        if (p_eloop_node->edit_ptr == edit_ptr)
        {
            p_eloop_node->ref_cnt--;
            if (0 == p_eloop_node->ref_cnt)
            {
                if (p_eloop_node->nhid)
                {
                    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_eloop_node->nhid, (sys_nh_info_com_t**)&p_nh_com_info));
                    if (p_nh_com_info)  CTC_UNSET_FLAG(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED);
                }

                sys_usw_nh_offset_free(lchip, is_l2edit?SYS_NH_ENTRY_TYPE_L2EDIT_LPBK:SYS_NH_ENTRY_TYPE_L3EDIT_LPBK, 1, p_eloop_node->edit_ptr);
                ctc_slist_delete_node(g_usw_nh_master[lchip]->eloop_list, &(p_eloop_node->head));
                mem_free(p_eloop_node);
            }
            return CTC_E_NONE;
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_update_loopback_l2edit(uint8 lchip, uint32 nhid, uint8 is_l2edit)
{
    ctc_slistnode_t* slist_node = NULL;
    sys_nh_eloop_node_t *p_eloop_node = NULL;

    sys_dsl2edit_t l2edit_param;
    sys_nh_info_dsnh_t nhinfo;

    sal_memset(&nhinfo, 0, sizeof(sys_nh_info_dsnh_t));
    sal_memset(&l2edit_param, 0, sizeof(sys_dsl2edit_t));
    CTC_SLIST_LOOP(g_usw_nh_master[lchip]->eloop_list, slist_node)
    {
        p_eloop_node = _ctc_container_of(slist_node, sys_nh_eloop_node_t, head);
        if (p_eloop_node->nhid == nhid)
        {
             CTC_ERROR_RETURN(_sys_usw_nh_get_nhinfo(lchip, nhid, &nhinfo));
             l2edit_param.ds_type  = nhinfo.drop_pkt ? SYS_NH_DS_TYPE_DISCARD:SYS_NH_DS_TYPE_L2EDIT;
             if(is_l2edit)
             {
                l2edit_param.l2_rewrite_type  =  DRV_FROM_TMM(lchip) ? DRV_ENUM(DRV_L2EDITTYPE_LOOPBACK):SYS_NH_L2EDIT_TYPE_LOOPBACK;
             }
             else
             {
                l2edit_param.l2_rewrite_type  =  DRV_FROM_TMM(lchip) ? DRV_ENUM(DRV_L3EDITTYPE_LOOPBACK):SYS_NH_L3EDIT_TYPE_LOOPBACK;
             }
              l2edit_param.dest_map = nhinfo.dest_map;
              l2edit_param.nexthop_ptr = nhinfo.dsnh_offset;
              l2edit_param.nexthop_ext = nhinfo.nexthop_ext;
              if ((SYS_NH_TYPE_ILOOP != nhinfo.nh_entry_type) && DRV_FROM_TMM(lchip))
              {
                  l2edit_param.bypass_ipe = 1;
              }
              l2edit_param.lb_with_ldp = p_eloop_node->lb_with_ldp;
              CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip,
                                                              is_l2edit?SYS_NH_ENTRY_TYPE_L2EDIT_LPBK: SYS_NH_ENTRY_TYPE_L3EDIT_LPBK,
                                                              p_eloop_node->edit_ptr,
                                                              &l2edit_param));
            return CTC_E_NONE;
        }
    }

    return CTC_E_NONE;
}
int32
sys_usw_nh_get_loopback_l2edit(uint8 lchip, uint32 edit_ptr ,uint32 *nhid, uint8 is_l2edit)
{
    ctc_slistnode_t* ctc_slistnode = NULL;
    sys_nh_eloop_node_t *p_eloop_node = NULL;

    CTC_SLIST_LOOP(g_usw_nh_master[lchip]->eloop_list, ctc_slistnode)
    {
        p_eloop_node = _ctc_container_of(ctc_slistnode, sys_nh_eloop_node_t, head);
        if (p_eloop_node->edit_ptr == edit_ptr)
        {
             *nhid = p_eloop_node->nhid;
            return CTC_E_NONE;
        }
    }

    return CTC_E_NOT_EXIST;
}

#define NH_L3EDIT

int32
sys_usw_nh_add_l3edit_tunnel(uint8 lchip, void* p_dsl3edit, uint8 edit_type, uint32* p_offset)  /*DsL3Edit*/
{
    int32 ret = CTC_E_NONE;
    sys_nh_db_edit_t edit_db;
    sys_nh_db_edit_t* p_db_out = NULL;
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];
    ds0_t ds;

    sal_memset(ds, 0, sizeof(ds));/*must memset for spool*/
    if (p_master->nh_table_info_array[edit_type].p_func)
    {
        CTC_ERROR_RETURN((*p_master->nh_table_info_array[edit_type].p_func)(lchip, (void*)(p_dsl3edit), &ds, p_offset));
    }
    edit_db.edit_type = edit_type;
    edit_db.offset = 0;
    edit_db.ds = &ds;
    edit_db.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_add(p_master->p_edit_spool, &edit_db, NULL, &p_db_out));

    ret = sys_usw_nh_set_asic_table(lchip, edit_type, p_db_out->offset, &ds);
    if (ret != CTC_E_NONE)
    {
        goto error1;
    }
    *p_offset = p_db_out->offset;

    return CTC_E_NONE;

error1:
    ctc_spool_remove(p_master->p_edit_spool, &edit_db, NULL);
    return ret;
}

int32
sys_usw_nh_remove_l3edit_tunnel(uint8 lchip, uint8 edit_type, uint32 offset)
{
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];
    sys_nh_db_edit_t edit_db;
    ds0_t ds;

    sal_memset(ds, 0, sizeof(ds));
    CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, edit_type, offset, &ds));
    edit_db.edit_type = edit_type;
    edit_db.offset = offset;
    edit_db.ds = &ds;
    edit_db.lchip = lchip;
    CTC_ERROR_RETURN(ctc_spool_remove(p_master->p_edit_spool, &edit_db, NULL));
    return CTC_E_NONE;
}

#define NH_MPLS_TUNNEL
int32
sys_usw_nh_lkup_mpls_tunnel(uint8 lchip, uint16 tunnel_id, sys_nh_db_mpls_tunnel_t** pp_mpls_tunnel)
{

    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];

    if (tunnel_id >= p_master->max_tunnel_id)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Exceed max tunnel id, tunnel id:%u \n", tunnel_id);
        return CTC_E_INVALID_PARAM;
    }

    *pp_mpls_tunnel = ctc_vector_get(p_master->tunnel_id_vec, tunnel_id);

    return CTC_E_NONE;

}

/**
 @brief Insert node into AVL tree
 */
int32
sys_usw_nh_add_mpls_tunnel(uint8 lchip, uint16 tunnel_id, sys_nh_db_mpls_tunnel_t* p_mpls_tunnel)
{
    int32 ret = CTC_E_NONE;
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];

    if (FALSE == ctc_vector_add(p_master->tunnel_id_vec, tunnel_id, p_mpls_tunnel))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;

    }

    return ret;
}

int32
sys_usw_nh_remove_mpls_tunnel(uint8 lchip, uint16 tunnel_id)
{

    int32 ret = CTC_E_NONE;
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];

    if (FALSE == ctc_vector_del(p_master->tunnel_id_vec, tunnel_id))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    return ret;
}

int32
sys_usw_nh_check_mpls_tunnel_is_spme(uint8 lchip, uint16 tunnel_id, uint8* spme_mode)
{
    sys_nh_db_mpls_tunnel_t* p_mpls_tunnel = NULL;

    CTC_ERROR_RETURN(sys_usw_nh_lkup_mpls_tunnel(lchip, tunnel_id, &p_mpls_tunnel));
    if (NULL == p_mpls_tunnel)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Tunnel label not exist\n");
			return CTC_E_NOT_EXIST;

    }
    if (CTC_FLAG_ISSET(p_mpls_tunnel->flag, SYS_NH_MPLS_TUNNEL_FLAG_IS_SPME))
    {
        *spme_mode = 1;
    }
    else
    {
        *spme_mode = 0;
    }
    return CTC_E_NONE;
}
#define ARP_ID

uint32
sys_usw_nh_get_arp_num(uint8 lchip)
{
    return g_usw_nh_master[lchip]->arp_id_hash->count;
}

sys_nh_db_arp_t*
sys_usw_nh_lkup_arp_id(uint8 lchip, uint32 arp_id)
{
    sys_nh_db_arp_t arp_db;
    sal_memset(&arp_db, 0, sizeof(sys_nh_db_arp_t));
    arp_db.arp_id = arp_id;
    return ctc_hash_lookup(g_usw_nh_master[lchip]->arp_id_hash, &arp_db);
}


int32
sys_usw_nh_add_arp_id(uint8 lchip, sys_nh_db_arp_t* p_arp)
{
    int32 ret = CTC_E_NONE;
    if (NULL == ctc_hash_insert(g_usw_nh_master[lchip]->arp_id_hash, p_arp))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    return ret;
}

int32
sys_usw_nh_remove_arp_id(uint8 lchip, sys_nh_db_arp_t* p_arp)
{
    int32 ret = CTC_E_NONE;
    if (NULL == ctc_hash_remove(g_usw_nh_master[lchip]->arp_id_hash, p_arp))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Not exist \n");
        return CTC_E_NOT_EXIST;
    }

    return ret;
}

#define NH_MISC

int32
_sys_usw_nh_set_glb_met_offset(uint8 lchip, uint32 start_offset, uint32 entry_num, bool is_set)
{
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint32* p_bmp, curr_offset;
    int32 i;

    if (0 == entry_num)
    {
        return CTC_E_NONE;
    }

    if ((start_offset + entry_num - 1) > p_nh_master->max_glb_met_offset)
    {
        return CTC_E_INVALID_PARAM;
    }


    if (NULL == (p_bmp = p_nh_master->p_occupid_met_offset_bmp))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
		return CTC_E_NOT_INIT;

    }

    for (i = 0; i < entry_num; i++)
    {
        curr_offset = start_offset + i;
        if (is_set)
        {
            CTC_SET_FLAG(p_bmp[(curr_offset >> BITS_SHIFT_OF_WORD)],
                         (1 << (curr_offset & BITS_MASK_OF_WORD)));
        }
        else
        {
            CTC_UNSET_FLAG(p_bmp[(curr_offset >> BITS_SHIFT_OF_WORD)],
                           (1 << (curr_offset & BITS_MASK_OF_WORD)));
        }
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_check_glb_met_offset(uint8 lchip, uint32 start_offset, uint32 entry_num,
                                      bool should_not_inuse)
{
    uint32* p_bmp, curr_offset;
    uint32 i;


    if (NULL == (p_bmp = g_usw_nh_master[lchip]->p_occupid_met_offset_bmp))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
		return CTC_E_NOT_INIT;
    }

    if (0 == entry_num)
    {
        return CTC_E_NONE;
    }
    for (i = 0; i < entry_num; i++)
    {
        curr_offset = start_offset + i;
        if (should_not_inuse && CTC_FLAG_ISSET(p_bmp[((curr_offset) >> BITS_SHIFT_OF_WORD)],
                                               (1 << (curr_offset & BITS_MASK_OF_WORD))))
        {
			return CTC_E_IN_USE;

        }

        if ((!should_not_inuse) && (!CTC_FLAG_ISSET(p_bmp[((curr_offset) >> BITS_SHIFT_OF_WORD)],
                                                    (1 << (curr_offset & BITS_MASK_OF_WORD)))))
        {
			return CTC_E_NOT_EXIST;

        }
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_get_max_ecmp(uint8 lchip, uint16* max_ecmp)
{
    *max_ecmp = g_usw_nh_master[lchip]->max_ecmp;

    return CTC_E_NONE;
}

int32
sys_usw_nh_set_max_ecmp(uint8 lchip, uint16 max_ecmp)
{
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint32 new_ecmp_grp_num = (0 == max_ecmp) ? MCHIP_CAP(SYS_CAP_NH_ECMP_GROUP_ID_NUM) : (MCHIP_CAP(SYS_CAP_NH_ECMP_MEMBER_NUM) / max_ecmp - 1);

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    /* the max ecmp num should be times of 4 */
    SYS_USW_NH_MAX_ECMP_CHECK(max_ecmp);

    if (p_nh_master->cur_ecmp_cnt != 0)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] ECMP already in use max path can not be reset \n");
			return CTC_E_IN_USE;
    }
    CTC_ERROR_RETURN(sys_usw_flow_stats_update_ecmp_stats(lchip, new_ecmp_grp_num, p_nh_master->max_ecmp_group_num, p_nh_master->h_ecmp_en));

    p_nh_master->max_ecmp = max_ecmp;
    p_nh_master->max_ecmp_group_num = new_ecmp_grp_num;
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER, 1);
    MCHIP_CAP(SYS_CAP_SPEC_ECMP_GROUP_NUM) = p_nh_master->max_ecmp_group_num + 1;
    MCHIP_CAP(SYS_CAP_SPEC_ECMP_MEMBER_NUM) = p_nh_master->max_ecmp;
    return CTC_E_NONE;
}

/**
 @brief This function is used to get l3ifid

 @param[in] nhid, nexthop id

 @param[out] p_l3ifid, l3 interface id

 @return CTC_E_XXX
 */
int32
sys_usw_nh_get_l3ifid(uint8 lchip, uint32 nhid, uint16* p_l3ifid)
{
    sys_nh_info_com_t* p_nhinfo;
    sys_nh_info_ipuc_t* p_ipuc_info;
    uint32 arp_id = 0;

    CTC_PTR_VALID_CHECK(p_l3ifid);
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if (nhid == SYS_NH_RESOLVED_NHID_FOR_DROP ||
        nhid == SYS_NH_RESOLVED_NHID_FOR_TOCPU)
    {
        *p_l3ifid = SYS_L3IF_INVALID_L3IF_ID;
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(
        sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo));

    switch (p_nhinfo->hdr.nh_entry_type)
    {
    case SYS_NH_TYPE_IPUC:
        p_ipuc_info = (sys_nh_info_ipuc_t*)(p_nhinfo);
        *p_l3ifid = p_ipuc_info->l3ifid;
        arp_id = p_ipuc_info->arp_id;
        break;

    case SYS_NH_TYPE_MPLS:
        {
            sys_nh_info_mpls_t* p_mpls_info;
            p_mpls_info = (sys_nh_info_mpls_t*)(p_nhinfo);
            *p_l3ifid = p_mpls_info->l3ifid;
            arp_id = p_mpls_info->arp_id;
            break;
        }

    case SYS_NH_TYPE_IP_TUNNEL:
        {
            sys_nh_info_ip_tunnel_t* p_ip_tunnel_info;
            p_ip_tunnel_info = (sys_nh_info_ip_tunnel_t*)(p_nhinfo);
            *p_l3ifid = p_ip_tunnel_info->l3ifid;
            break;
        }

    case SYS_NH_TYPE_MISC:
        {

            sys_nh_info_misc_t* p_misc_info;
            p_misc_info = (sys_nh_info_misc_t*)(p_nhinfo);
            *p_l3ifid = p_misc_info->l3ifid;
            break;
        }
    case SYS_NH_TYPE_OVERLAY:
        {
            sys_nh_info_overlay_t* p_overlay_info;
            sys_nh_db_ol_tunnel_t* tunnel_db = NULL;
            p_overlay_info = (sys_nh_info_overlay_t*)(p_nhinfo);
            tunnel_db = _sys_usw_nh_lkup_tunnel(lchip, p_overlay_info->dest_logic_port);
            if (tunnel_db)
            {
                arp_id = tunnel_db->arp_id;
            }
            break;
        }
    case SYS_NH_TYPE_SRV6:
        {
            sys_nh_info_srv6_t* p_srv6_info;
            p_srv6_info = (sys_nh_info_srv6_t*)(p_nhinfo);
            *p_l3ifid = p_srv6_info->l3ifid;
            break;
        }
    default:
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Nexthop type is invalid \n");
		return CTC_E_INVALID_CONFIG;

    }

    if (arp_id)
    {
        sys_nh_db_arp_t *p_arp = NULL;
        p_arp = (sys_usw_nh_lkup_arp_id(lchip, arp_id));
        if (NULL == p_arp)
        {
            return CTC_E_NOT_EXIST;
        }

        if (p_arp && !CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_DROP) && !CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU)
            && !CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_ECMP_IF))
        {
            /*update l3if id*/
            *p_l3ifid = p_arp->l3if_id;
        }


    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_get_mcast_nh(uint8 lchip, uint32 group_id, uint32* nhid, void** pp_db)
{
    sys_nh_info_mcast_t* p_mcast_db = NULL;
    p_mcast_db =  ctc_vector_get(g_usw_nh_master[lchip]->mcast_group_vec, group_id);
    if (NULL == p_mcast_db)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    *nhid = p_mcast_db->hdr.nh_id;
    if (pp_db != NULL)
    {
        *pp_db = (void *)p_mcast_db;
    }
    return CTC_E_NONE;
}


int32
sys_usw_nh_add_mcast_db(uint8 lchip, uint32 group_id, void* data)
{
    if (FALSE == ctc_vector_add(g_usw_nh_master[lchip]->mcast_group_vec, group_id, data))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_del_mcast_db(uint8 lchip, uint32 group_id)
{
    if (FALSE == ctc_vector_del(g_usw_nh_master[lchip]->mcast_group_vec, group_id))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;

    }

    return CTC_E_NONE;
}

int32
_sys_usw_misc_nh_create(uint8 lchip, uint32 nhid, sys_usw_nh_type_t nh_param_type)
{
    sys_nh_param_special_t nh_para;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "nhid = %u\n", nhid);

    switch (nh_param_type)
    {
    case SYS_NH_TYPE_DROP:
    case SYS_NH_TYPE_TOCPU:
    case SYS_NH_TYPE_UNROV:
        break;

    default:
        CTC_ERROR_RETURN(CTC_E_INVALID_PARAM);
    }

    sal_memset(&nh_para, 0, sizeof(sys_nh_param_special_t));
    nh_para.hdr.nhid = nhid;
    nh_para.hdr.nh_param_type = nh_param_type;
    nh_para.hdr.is_internal_nh = FALSE;
    nh_para.hdr.have_dsfwd = TRUE;
    nh_para.hdr.have_dsfwd1 = TRUE;

    CTC_ERROR_RETURN(sys_usw_nh_api_create(lchip, (sys_nh_param_com_t*)(&nh_para)));
    return CTC_E_NONE;
}

int32
_sys_usw_nh_get_mcast_member(void* array_data, uint32 group_id, void* p_data)
{
    sys_nh_mcast_traverse_t* p_mcast_traverse = NULL;
    uint32 nhid = 0;
    sys_nh_info_mcast_t* p_mcast_db = NULL;

    ctc_nh_info_t nh_info;
    ctc_mcast_nh_param_member_t nh_member;
    uint8 lchip = 0;

    p_mcast_traverse = (sys_nh_mcast_traverse_t*)p_data;
    lchip = p_mcast_traverse->lchip;

    CTC_ERROR_RETURN(_sys_usw_nh_get_mcast_nh(lchip, group_id, &nhid, (void **)&p_mcast_db));
    SYS_NH_UNLOCK;
    sal_memset(&nh_info, 0, sizeof(ctc_nh_info_t));
    nh_info.buffer = &nh_member;
    nh_info.buffer_len = 1;
    do
    {
        sal_memset(&nh_member, 0, sizeof(ctc_mcast_nh_param_member_t));
        sys_usw_nh_get_mcast_member_info(lchip, p_mcast_db, &nh_info);
        p_mcast_traverse->fn(p_mcast_db->basic_met_offset, &nh_member, p_mcast_traverse->user_data);
        nh_info.start_index = nh_info.next_query_index;
    }while(!nh_info.is_end);
    SYS_NH_LOCK;

    return CTC_E_NONE;
}

int32
_sys_usw_nh_traverse_mcast(uint8 lchip, ctc_nh_mcast_traverse_fn fn, ctc_nh_mcast_traverse_t* p_data)
{
    int32 ret = CTC_E_NONE;
    vector_traversal_fn2 fn2 = NULL;
    sys_nh_mcast_traverse_t mcast_traverse;

    fn2 = _sys_usw_nh_get_mcast_member;
    sal_memset(&mcast_traverse, 0, sizeof(sys_nh_mcast_traverse_t));
    mcast_traverse.user_data = p_data->user_data;
    mcast_traverse.fn = fn;
    mcast_traverse.lchip = p_data->lchip_id;

    ctc_vector_traverse2(g_usw_nh_master[lchip]->mcast_group_vec, 0, fn2, &mcast_traverse);
    return ret;
}


int32
_sys_usw_nh_set_nh_map(uint8 lchip, uint32 dsnh_ptr, uint32 dsnh_offset)
{
    uint32 cmd = 0;
    uint32 index = 0;
    uint8 offset = 0;
    DsNextHopIdMapPointer_m ds;
    index = (dsnh_ptr & ((g_usw_nh_master[lchip]->nh_mapper_num << 3) - 1)) >> 3;
    offset = dsnh_ptr & 0x7;
    cmd = DRV_IOR(DsNextHopIdMapPointer_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index , cmd, &ds));
    DRV_SET_FIELD_V(lchip, DsNextHopIdMapPointer_t, offset, &ds, dsnh_offset);
    cmd = DRV_IOW(DsNextHopIdMapPointer_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, index , cmd, &ds));
    return CTC_E_NONE;
}

extern sys_nh_db_srh_t*
_sys_usw_nh_lkup_srh_id(uint8 lchip, uint32 srh_id);

int32
sys_usw_nh_lkup_srh_edit(uint8 lchip, uint32 srh_id, sys_nh_db_srh_t** pp_srh)
{
    *pp_srh = _sys_usw_nh_lkup_srh_id(lchip, srh_id);
    return CTC_E_NONE;
}

#define ___ARP___

STATIC int32
_sys_usw_nh_arp_free_resource(uint8 lchip, sys_nh_db_arp_t* p_arp)
{

    if (p_arp->offset)
    {
        sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, p_arp->offset);
    }
    if (p_arp->offset_dyn)
    {
        sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, 1, p_arp->offset_dyn);
    }

    if (p_arp->ldp_mac_profile)
    {
        sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_LDP_MAC_PROFILE, 1, p_arp->ldp_mac_profile);
    }

    if (p_arp->destmap_profile)
    {
        uint32 offset = p_arp->destmap_profile;
        sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_DESTMAP_PROFILE, 1, offset);
    }

    if (p_arp->dsfwd_offset)
    {
        sys_usw_nh_offset_free(lchip, DRV_FROM_AT(lchip)? SYS_NH_ENTRY_TYPE_FWD_HALF1 : SYS_NH_ENTRY_TYPE_FWD_HALF, 1, p_arp->dsfwd_offset);
    }
    if (p_arp->pd->nh_list)
    {
        mem_free(p_arp->pd->nh_list);
    }

    mem_free(p_arp->pd);

    sys_usw_nh_remove_arp_id(lchip, p_arp);
    mem_free(p_arp);
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_build_arp_info(uint8 lchip, sys_nh_db_arp_t* p_arp, ctc_nh_nexthop_mac_param_t* p_param, sys_l3if_prop_t* l3if)
{
    uint8 gchip = 0;
    uint32 gport = 0;
    uint8 l3if_vlan_num = 0;
    uint8 arp_vlan_num = 0;
    uint8 svlan_num_match = 0;
    uint8 vlan_from_arp = 0;
    uint8 vlan_from_l3if = 0;
    /*db*/
    CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_PORT_VALID);
    sys_usw_get_gchip_id(lchip, &gchip);

    /*1. gport*/
    if (((l3if->l3if_type == CTC_L3IF_TYPE_SERVICE_IF) && (0 == l3if->bind_en))
        || (l3if->l3if_type == CTC_L3IF_TYPE_VLAN_IF))
    {
        gport = p_param->gport;
    }
    else
    {
        gport = l3if->gport;
    }
    if (CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_DISCARD))
    {
        CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_FLAG_DROP);
        gport = CTC_MAP_LPORT_TO_GPORT(gchip,SYS_RSV_PORT_DROP_ID);
    }
    else
    {
        CTC_UNSET_FLAG(p_arp->flag, SYS_NH_ARP_FLAG_DROP);
    }

    if (CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_REDIRECT_TO_CPU))
    {
        CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU);
        gport = CTC_GPORT_RCPU(gchip);
    }
    else
    {
        CTC_UNSET_FLAG(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU);
    }
    p_arp->gport = gport;

    /*2. mac*/
    sal_memcpy(p_arp->mac_da, p_param->mac, sizeof(mac_addr_t));

    /*3. vlan*/
    CTC_UNSET_FLAG(p_arp->flag, (SYS_NH_ARP_VLAN_VALID | SYS_NH_ARP_CVLAN_VALID));
    p_arp->output_vid = 0;
    p_arp->output_cvid = 0;
    CTC_UNSET_FLAG(p_arp->flag, SYS_NH_ARP_IPUC_L2_EDIT);

    arp_vlan_num = (CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID)? 1 : 0)
                 + ((p_param->cvlan_id || CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_CVLAN_VALID))? 1 : 0);
    l3if_vlan_num = (l3if->vlan_id? 1 : 0) + (l3if->cvlan_id? 1 : 0);
    if (((l3if->l3if_type == CTC_L3IF_TYPE_SERVICE_IF) && (0 == l3if->bind_en))
        || (l3if->l3if_type == CTC_L3IF_TYPE_PHY_IF))
    {
        if (arp_vlan_num
            || (p_param->if_id && (0xFFFF == p_param->vlan_id)))/*for no vlan update to one vlan, alloc dsedit but not do vlan edit*/
        {
            p_arp->is_8w = (arp_vlan_num > 1)? 1 : 0;/*double vlan use 2X*/
            vlan_from_arp = 1;
            CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_IPUC_L2_EDIT);
        }
    }
    else/*CTC_L3IF_TYPE_VLAN_IF/CTC_L3IF_TYPE_SUB_IF/CTC_L3IF_TYPE_SERVICE_IF*/
    {
        svlan_num_match = CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID) && l3if->vlan_id;
        if ((l3if_vlan_num == 2) && (!DRV_FROM_AT(lchip)))/*cvlan from l3if and svlan from dsedit, for Arctic, double vlan from l3if*/
        {
            vlan_from_l3if = 1;
            CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_IPUC_L2_EDIT);
        }
        else if ((0 == svlan_num_match) && (arp_vlan_num == 1) && (l3if_vlan_num == 1)
            && p_param->if_id)/*cvlan from l3if and svlan from dsedit*/
        {
            vlan_from_arp = 1;
            CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_IPUC_L2_EDIT);
        }
        else
        {
            vlan_from_l3if = 1;
        }
    }

    if (vlan_from_arp)
    {
        if (CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID))
        {
            CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_VLAN_VALID);
            p_arp->output_vid = p_param->vlan_id;
            p_arp->output_vlan_is_svlan = 1;
        }
        if ((p_param->cvlan_id || CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_CVLAN_VALID)))
        {
            CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_CVLAN_VALID);
            p_arp->output_cvid = p_param->cvlan_id;
        }
    }
    else if (vlan_from_l3if)
    {
        if (l3if->vlan_id)
        {
            CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_VLAN_VALID);
            p_arp->output_vid = l3if->vlan_id;
            p_arp->output_vlan_is_svlan = 1;
        }
        if (l3if->cvlan_id)
        {
            CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_CVLAN_VALID);
            p_arp->output_cvid = l3if->cvlan_id;
        }
    }


    if (p_param->if_id || !CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_DROP))
    {
        CTC_SET_FLAG(p_arp->flag, SYS_NH_ARP_L3IF_VALID);
    }
    else
    {
        CTC_UNSET_FLAG(p_arp->flag, SYS_NH_ARP_L3IF_VALID);
    }

    return CTC_E_NONE;
}


/**
 @brief Add Next Hop Router Mac
*/
int32
_sys_usw_nh_add_nexthop_mac(uint8 lchip, uint32 arp_id, ctc_nh_nexthop_mac_param_t* p_param)
{
    int32 ret = CTC_E_NONE;
    sys_nh_db_arp_t*  p_arp = NULL;
     sys_l3if_prop_t l3if;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);


    sal_memset(&l3if,0,sizeof(sys_l3if_prop_t));
    /*check flag*/
    if ( (CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_DISCARD)
            + CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_REDIRECT_TO_CPU)) > 1)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_IS_CPU_PORT(p_param->gport))
    {
        return CTC_E_INVALID_PARAM;
    }

    if ((arp_id < 1) || (arp_id > 0xFFFFF))/*up to 1M arp*/
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID))
    {
        CTC_MAX_VALUE_CHECK(p_param->vlan_id, CTC_MAX_VLAN_ID);
    }

#ifdef WARMBOOT
    if(CTC_WB_ENABLE(lchip) && g_usw_nh_master[lchip]->arp_id_hash->count >= (SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_IPUC_HOST)+SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_IPUC_ND)))
    {
        return CTC_E_NO_RESOURCE;
    }
#endif
    if (p_param->cvlan_id > CTC_MAX_VLAN_ID)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (!p_param->if_id)
    {
        ret = sys_usw_l3if_get_l3if_info_with_port_and_vlan( lchip,  p_param->gport, p_param->vlan_id, p_param->cvlan_id, &l3if);
        if (ret == CTC_E_NOT_EXIST)
        {
            if ((!CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_DISCARD))
                && (!CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_REDIRECT_TO_CPU)))
            {
                return ret;
            }
            l3if.l3if_type = 0x07;  /*invalid l3if type*/
        }
    }
    else if (p_param->if_id)
    {
        l3if.l3if_id = p_param->if_id;
        CTC_ERROR_RETURN(sys_usw_l3if_get_l3if_info(lchip, 1, &l3if));
        if (l3if.l3if_type != CTC_L3IF_TYPE_SERVICE_IF && l3if.l3if_type != CTC_L3IF_TYPE_SUB_IF && CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID) &&
           (p_param->cvlan_id || CTC_FLAG_ISSET(p_param->flag, CTC_NH_NEXTHOP_MAC_CVLAN_VALID)))
        {
            return CTC_E_INVALID_CONFIG;
        }
    }

    /*alloc*/
    p_arp = sys_usw_nh_lkup_arp_id(lchip, arp_id);
    if (NULL == p_arp)
    {
        p_arp  = (sys_nh_db_arp_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_arp_t));
        if (NULL == p_arp)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;

        }
        sal_memset(p_arp, 0, sizeof(sys_nh_db_arp_t));

        /*alloc*/
        p_arp->arp_id = arp_id;
        p_arp->l3if_type = l3if.l3if_type;
        p_arp->l3if_id  = l3if.l3if_id;


        p_arp->pd = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_arp_pdata_t));
        if (NULL == p_arp->pd)
        {
            ret = CTC_E_NO_MEMORY;
            goto error0;
        }
        sal_memset(p_arp->pd, 0, sizeof(sys_nh_db_arp_pdata_t));

        p_arp->pd->nh_list = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(ctc_list_pointer_t));
        if (NULL == p_arp->pd->nh_list)
        {
            ret = CTC_E_NO_MEMORY;
            goto error0;
        }
        ctc_list_pointer_init(p_arp->pd->nh_list);

        ret = _sys_usw_nh_build_arp_info(lchip, p_arp, p_param, &l3if);

        if (CTC_E_NONE != ret)
        {
           goto error0;
        }

        ret = sys_usw_nh_add_arp_id(lchip, p_arp);
        if (CTC_E_NONE != ret)
        {
           goto error0;
        }

        ret = sys_usw_nh_write_entry_arp(lchip, p_arp);
        if (ret != CTC_E_NONE)
        {
            goto error1;
        }
        return CTC_E_NONE;

    }
    else
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry already exist \n");
			return CTC_E_EXIST;

    }

error1:
    sys_usw_nh_remove_arp_id(lchip, p_arp);

error0:
    _sys_usw_nh_arp_free_resource(lchip, p_arp);
    return ret;

}

/**
 @brief Remove Next Hop Router Mac
*/
int32
_sys_usw_nh_remove_nexthop_mac(uint8 lchip, uint32 arp_id)
{
    sys_nh_db_arp_t*  p_arp = NULL;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    if ((arp_id < 1) || (arp_id > 0xFFFFF))
    {
        return CTC_E_INVALID_PARAM;
    }

    p_arp = (sys_usw_nh_lkup_arp_id(lchip, arp_id));
    if (!p_arp)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
			return CTC_E_NOT_EXIST;

    }

    if(p_arp->ref_cnt)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Host nexthop already in use. \n");
			return CTC_E_IN_USE;

    }

    if (CTC_FLAG_ISSET(p_arp->flag , SYS_NH_ARP_ECMP_IF))
    {
        sal_memset(p_arp->mac_da, 0, sizeof(mac_addr_t));
        sys_usw_nh_write_entry_arp(lchip, p_arp);
    }

    _sys_usw_nh_arp_free_resource(lchip, p_arp);
    return CTC_E_NONE;

}

/**
 @brief Update Next Hop Router Mac
*/
int32
_sys_usw_nh_update_nexthop_mac(uint8 lchip, uint32 arp_id, ctc_nh_nexthop_mac_param_t* p_new_param)
{
    sys_nh_db_arp_t*  p_arp = NULL;
    int32 ret = 0;
    uint8 cvlan_valid = 0;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    CTC_PTR_VALID_CHECK(p_new_param);

    if ( (CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_DISCARD)
            + CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_REDIRECT_TO_CPU)) > 1)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_IS_CPU_PORT(p_new_param->gport))
    {
        return CTC_E_INVALID_PARAM;
    }

    if ((arp_id < 1) || (arp_id > 0xFFFFF))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID))
    {
        CTC_MAX_VALUE_CHECK(p_new_param->vlan_id, CTC_MAX_VLAN_ID);
    }

    if (CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_CVLAN_VALID))
    {
        CTC_MAX_VALUE_CHECK(p_new_param->cvlan_id, CTC_MAX_VLAN_ID);
    }
    cvlan_valid = (p_new_param->cvlan_id || CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_CVLAN_VALID))?1:0;
    p_arp = (sys_usw_nh_lkup_arp_id(lchip, arp_id));
    if (NULL == p_arp)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Arp Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }
    else
    {
        sys_l3if_prop_t l3if;
        sal_memset(&l3if, 0, sizeof(sys_l3if_prop_t));
       if (!p_new_param->if_id)
       {
            ret = sys_usw_l3if_get_l3if_info_with_port_and_vlan( lchip,  p_new_param->gport, p_new_param->vlan_id, p_new_param->cvlan_id, &l3if);
            if (ret == CTC_E_NOT_EXIST)
            {
                if (!CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_DISCARD))
                {
                    return ret;
                }
                l3if.l3if_type = 0x07;  /*invalid l3if type*/
            }

          if ((p_arp->l3if_id != l3if.l3if_id ||p_arp->l3if_type != l3if.l3if_type) && p_arp->ref_cnt)
          {
              SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Update L3 interface failed old l3if_id :%d new l3if_id:%d ,ref cnt:%u\n",
                            p_arp->l3if_id, l3if.l3if_id,p_arp->ref_cnt);
             return CTC_E_INVALID_PARAM;
          }
          p_arp->l3if_type = l3if.l3if_type;
          p_arp->l3if_id  = l3if.l3if_id;
       }
       else if (p_new_param->if_id)
       {
            l3if.l3if_id = p_new_param->if_id;
            CTC_ERROR_RETURN(sys_usw_l3if_get_l3if_info(lchip, 1, &l3if));

            if ((p_new_param->if_id != p_arp->l3if_id) && p_arp->ref_cnt)
            {
               return CTC_E_INVALID_PARAM;
            }

            if (((p_arp->l3if_type == CTC_L3IF_TYPE_SERVICE_IF && CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_VLAN_VALID)&& CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_CVLAN_VALID)) !=
                (l3if.l3if_type == CTC_L3IF_TYPE_SERVICE_IF && CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID)&& cvlan_valid)) && p_arp->ref_cnt)
            {
                return CTC_E_INVALID_CONFIG;
            }

            if (p_arp->l3if_type != CTC_L3IF_TYPE_SERVICE_IF && p_arp->l3if_type != CTC_L3IF_TYPE_SUB_IF && CTC_FLAG_ISSET(p_new_param->flag, CTC_NH_NEXTHOP_MAC_VLAN_VALID)&& cvlan_valid)
            {
                return CTC_E_INVALID_CONFIG;
            }
            p_arp->l3if_type = l3if.l3if_type;
            p_arp->l3if_id  = l3if.l3if_id;
       }
       CTC_ERROR_RETURN(_sys_usw_nh_build_arp_info(lchip, p_arp, p_new_param, &l3if));
    }

    CTC_ERROR_RETURN(sys_usw_nh_write_entry_arp(lchip, p_arp));

    return CTC_E_NONE;

}
int32
sys_usw_nh_unbind_arp_cb(uint8 lchip, uint32 arp_id, uint8 use_cb, void* node)
{
    sys_nh_db_arp_t*  p_arp = NULL;
    p_arp = (sys_usw_nh_lkup_arp_id(lchip, arp_id));
    if (NULL == p_arp)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;

    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ARP, 1);
    if (use_cb && node)
    {
        sys_nh_db_arp_nh_node_t* p_arp_nh_node = node;
        ctc_list_pointer_delete(p_arp->pd->nh_list, &(p_arp_nh_node->head));
        mem_free(node);
    }
    p_arp->ref_cnt = (p_arp->ref_cnt)? (p_arp->ref_cnt - 1) : 0;

    if (!p_arp->ref_cnt)
    {
        if ((p_arp->destmap_profile) && CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_PORT_VALID))
        {
            sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_DESTMAP_PROFILE, 1,  p_arp->destmap_profile);
            p_arp->destmap_profile = 0;
        }
        if (p_arp->offset_dyn)
        {
            sys_usw_nh_offset_free(lchip, p_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, 1, p_arp->offset_dyn);
            p_arp->offset_dyn = 0;
        }
        if (p_arp->offset)
        {
            sys_usw_nh_offset_free(lchip, p_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W : SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, p_arp->offset);
            p_arp->offset = 0;
        }

        if (p_arp->ldp_mac_profile)
        {
            sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_LDP_MAC_PROFILE, 1, p_arp->ldp_mac_profile);
            p_arp->ldp_mac_profile = 0;
        }
        if (p_arp->dsfwd_offset)
        {
            sys_usw_nh_offset_free(lchip, DRV_FROM_AT(lchip)? SYS_NH_ENTRY_TYPE_FWD_HALF1 : SYS_NH_ENTRY_TYPE_FWD_HALF, 1, p_arp->dsfwd_offset);
            p_arp->dsfwd_offset = 0;
        }
    }

    return CTC_E_NONE;
}
int32
sys_usw_nh_bind_arp_cb(uint8 lchip, sys_nh_info_arp_param_t* p_arp_parm, uint32 arp_id)
{
    sys_nh_db_arp_t*  p_arp = NULL;
    int32 ret = CTC_E_NONE;
    uint32 offset = 0;
    uint8 use_arp_profile = 0;
    uint8 use_dynamic_l2edit = 0;
    uint8 use_static_l2edit = 0;
    uint8 use_ldp_mac_profile = 0;
    uint8 binding_cb = 0;
    sys_nh_db_arp_nh_node_t* p_arp_nh_node = NULL;

    p_arp = (sys_usw_nh_lkup_arp_id(lchip, arp_id));
    if (NULL == p_arp)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
        return CTC_E_NOT_EXIST;
    }

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ARP, 1);


    if (SYS_NH_TYPE_IPUC == p_arp_parm->nh_entry_type)
    {
        if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_IPUC_L2_EDIT)||(p_arp_parm->use_l2edit))
        {
            use_dynamic_l2edit = 1;
        }

        use_static_l2edit = p_arp_parm->use_static_l2edit;
        if (p_arp->offset)/*if already alloced static edit, then use static edit*/
        {
            use_static_l2edit = 1;
            use_dynamic_l2edit = 0;
        }

        if (p_arp_parm->is_aps)
        {
            use_arp_profile = 1;
            use_dynamic_l2edit = 1;
        }
        else
        {
            p_arp_nh_node =  mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_arp_nh_node_t));
            if (NULL == p_arp_nh_node)
            {
                return CTC_E_NO_MEMORY;
            }

            sal_memset(p_arp_nh_node, 0, sizeof(sys_nh_db_arp_nh_node_t));
            p_arp_nh_node->nhid = p_arp_parm->nh_id;
            ctc_list_pointer_insert_tail(p_arp->pd->nh_list, &(p_arp_nh_node->head));
            p_arp->pd->updateNhp = p_arp_parm->updateNhp;
            p_arp_parm->p_arp_nh_node = p_arp_nh_node;
            binding_cb = 1;
        }
    }
    else if (SYS_NH_TYPE_OVERLAY_VNI == p_arp_parm->nh_entry_type
         && g_usw_nh_master[lchip]->ldp_mac_profile_en)
    {
        if (0 == p_arp->ldp_mac_profile)
        {
            ret = sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_LDP_MAC_PROFILE, 1, &offset);
            if (ret != CTC_E_NONE)
            {
                use_arp_profile = 1;
                use_static_l2edit = 1;
            }
            else
            {
                p_arp->ldp_mac_profile = offset;
                use_ldp_mac_profile = 2;
            }
        }
    }
    else
    {
        use_arp_profile = 1;
        use_static_l2edit = 1;
    }

    if (use_arp_profile && (0 == p_arp->destmap_profile) && CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_PORT_VALID))
    {
        CTC_ERROR_GOTO(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_DESTMAP_PROFILE, 1,  &offset), ret, err);
        p_arp->destmap_profile = offset;
        use_arp_profile = 2;
    }
    if (use_dynamic_l2edit && (0 == p_arp->offset_dyn))
    {
        ret = sys_usw_nh_offset_alloc(lchip, p_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, 1, &offset);
        if (ret == CTC_E_NONE)
        {
            p_arp->offset_dyn = offset;
            use_dynamic_l2edit = 2;
        }
        else if (ret == CTC_E_NO_RESOURCE)/*if no dynamic resource, then use static resorce*/
        {
            use_static_l2edit = 1;
        }
        else
        {
            goto err;
        }
    }
    if (use_static_l2edit && (0 == p_arp->offset))
    {
        CTC_ERROR_GOTO(sys_usw_nh_offset_alloc(lchip, p_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W : SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, &offset), ret, err);
        p_arp->offset = offset;
        use_static_l2edit = 2;
#if 0
        if (p_arp->offset_dyn)/*if already alloced dynamic edit, change to static edit*/
        {
            sys_nh_db_arp_t* p_arp = NULL;
            ctc_list_pointer_node_t* node = NULL;
            CTC_LIST_POINTER_LOOP(node, p_arp->pd->nh_list)
            {
                p_arp_nh_node = _ctc_container_of(node, sys_nh_db_arp_nh_node_t, head);
                CTC_ERROR_RETURN(p_arp->pd->updateNhp(lchip, p_arp, p_arp_nh_node->nhid));
            }
            sys_usw_nh_offset_free(lchip, p_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, 1, p_arp->offset_dyn);
            p_arp->offset_dyn = 0;
        }
#endif
    }

    CTC_ERROR_GOTO(sys_usw_nh_write_entry_arp(lchip, p_arp), ret, err);
    p_arp->ref_cnt++;
    return CTC_E_NONE;
err:
    if (2 == use_static_l2edit)
    {
        sys_usw_nh_offset_free(lchip, p_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W : SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, p_arp->offset);
        p_arp->offset = 0;
    }
    if (2 == use_dynamic_l2edit)
    {
        sys_usw_nh_offset_free(lchip, p_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, 1, p_arp->offset_dyn);
        p_arp->offset_dyn = 0;
    }

    if (2 == use_ldp_mac_profile)
    {
        sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_LDP_MAC_PROFILE, 1, p_arp->ldp_mac_profile);
        p_arp->ldp_mac_profile = 0;
    }

    if (2 == use_arp_profile)
    {
        sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_DESTMAP_PROFILE, 1,  p_arp->destmap_profile);
        p_arp->destmap_profile = 0;
    }
    if(binding_cb)
    {
        ctc_list_pointer_delete(p_arp->pd->nh_list, &(p_arp_nh_node->head));
        mem_free(p_arp_nh_node);
    }

    return ret;
}
int32 
sys_usw_nh_arp_alloc_dsfwd(uint8 lchip, sys_nh_db_arp_t*  p_arp, uint32* p_dsfwd_offset)
{
    int32 ret = CTC_E_NONE;
    uint32 dsfwd_offset = 0;
    sys_nh_param_dsfwd_t dsfwd_param;
    sys_nh_entry_table_type_t entry_type = 0;

    sal_memset(&dsfwd_param, 0, sizeof(dsfwd_param));
    dsfwd_offset = p_arp->dsfwd_offset;
    if (dsfwd_offset == 0)
    {
        /* alloc dsfwdptr*/
        CTC_ERROR_RETURN(sys_usw_nh_map_entry_type(lchip, DRV_FROM_AT(lchip)? SYS_API_NH_DSFWD_HALF1 : SYS_API_NH_DSFWD_HALF, &entry_type));
        CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, entry_type, 1, &dsfwd_offset));
        /* write dsfwd */
        dsfwd_param.is_mcast = FALSE;
        if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU))
        {
            dsfwd_param.dest_chipid  =  SYS_MAP_CTC_GPORT_TO_GCHIP(p_arp->gport);
            dsfwd_param.is_lcpu    =   CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU);
            dsfwd_param.dsnh_offset    =   CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_ARP_MISS, 0);
        }
        else if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_DROP))
        {
            dsfwd_param.dest_chipid  =  SYS_MAP_CTC_GPORT_TO_GCHIP(p_arp->gport);
            dsfwd_param.drop_pkt = 1;
        }
        else
        {
            dsfwd_param.dest_chipid  =  SYS_MAP_CTC_GPORT_TO_GCHIP(p_arp->gport);
            dsfwd_param.dest_id = p_arp->destmap_profile? p_arp->destmap_profile : CTC_MAP_GPORT_TO_LPORT(p_arp->gport);
            dsfwd_param.use_destmap_profile = p_arp->destmap_profile? 1 : 0;
        }
        dsfwd_param.dsfwd_offset = dsfwd_offset;
        dsfwd_param.is_dsfwd1 = DRV_FROM_AT(lchip)? 1 : 0;
        CTC_ERROR_GOTO(sys_usw_nh_write_entry_dsfwd(lchip, &dsfwd_param), ret, error0);
        p_arp->dsfwd_offset = dsfwd_offset;
    }
    *p_dsfwd_offset = dsfwd_offset;
    return ret;

    error0:
    sys_usw_nh_offset_free(lchip, entry_type, 1, dsfwd_offset);

    return ret;

}
#define ___UDF___

int32
_sys_usw_nh_add_udf_profile(uint8 lchip, ctc_nh_udf_profile_param_t* p_edit)
{
    uint8 index = 0;
    EpePktProcFlexTunnelCtl_m flex_ctl;
    EpePktProcFlexTunnelCtl2_m flex_ctl2;
    uint32 cmd = 0;
    uint32 l4_type = 0;
    uint32 field_id = 0;
    uint8 field_step = 0;
    uint8 profile_id = p_edit->profile_id;
    uint8 replacePos = 0;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint32 dest_hw[4] = {0};

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "profile_id = %u, udf_offset_type = %u, udf_edit_length = %u\n",
        p_edit->profile_id, p_edit->offset_type, p_edit->edit_length);
    for (index = 0; index < CTC_NH_UDF_MAX_EDIT_NUM; index++)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "UDF edit index = %u , type = %u, offset = %u, length = 0x%x\n",
        index, p_edit->edit[index].type, p_edit->edit[index].offset, p_edit->edit[index].length);
    }

    /*parameter check*/
    if (!profile_id || profile_id > SYS_NH_UDF_PROF_NUM)
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_MAX_VALUE_CHECK(p_edit->offset_type,CTC_NH_UDF_OFFSET_TYPE_RAW);

    if (!p_edit->edit_length || p_edit->edit_length > 16 || (p_edit->edit_length&0x1))
    {
        return CTC_E_INVALID_PARAM;
    }

    if (p_edit->hdr_option_length >= 16)
    {
        return CTC_E_INVALID_PARAM;
    }

    for (index = 0; index < CTC_NH_UDF_MAX_EDIT_NUM; index++)
    {
        CTC_MAX_VALUE_CHECK(p_edit->edit[index].type, 3);
        if (p_edit->edit[index].type)
        {
            if (p_edit->edit[index].offset & 0x1)
            {
                return CTC_E_INVALID_PARAM;
            }

            if (p_edit->edit[index].length > 16 || !p_edit->edit[index].length)
            {
                return CTC_E_INVALID_PARAM;
            }

            if (p_edit->edit[index].offset +  p_edit->edit[index].length > (p_edit->edit_length*8))
            {
                return CTC_E_INVALID_PARAM;
            }

            if (p_edit->edit[index].length + p_edit->edit[index].offset < 16)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "UDF edit index %u out of range of FlexHeader\n",index);
                return CTC_E_INVALID_CONFIG;
            }
        }
    }


    if (CTC_IS_BIT_SET(p_nh_master->udf_profile_bitmap, profile_id))
    {
        return CTC_E_EXIST;
    }

    if (p_edit->offset_type==CTC_NH_UDF_OFFSET_TYPE_UDP)
    {
        l4_type = 1;
    }
    else if (p_edit->offset_type==CTC_NH_UDF_OFFSET_TYPE_GRE)
    {
        l4_type = 2;
    }
    else if (p_edit->offset_type==CTC_NH_UDF_OFFSET_TYPE_GRE_WITH_KEY)
    {
        l4_type = 3;
    }

    //field_step = (EpePktProcFlexTunnelCtl_flexArray_1_existIpHeader_f - EpePktProcFlexTunnelCtl_flexArray_0_existIpHeader_f);
    field_step = 1;

    cmd = DRV_IOR(EpePktProcFlexTunnelCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_ctl));

    field_id = EpePktProcFlexTunnelCtl_flexArray_0_existIpHeader_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, ((p_edit->offset_type==CTC_NH_UDF_OFFSET_TYPE_RAW)?0:1));

    field_id = EpePktProcFlexTunnelCtl_flexArray_0_flexHdrLen_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, (p_edit->edit_length>>1));

    field_id = EpePktProcFlexTunnelCtl_flexArray_0_l4HdrType_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, l4_type);

    field_id = EpePktProcFlexTunnelCtl_flexArray_0_lenFieldDeltaValue_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, p_edit->hdr_option_length);

    if (DRV_FROM_TMM(lchip))
    {
        if((1 == p_edit->edit[0].type) || (1 == p_edit->edit[1].type))
        {
            return CTC_E_NOT_SUPPORT;
        }
        for (index = 0; index < ((p_edit->edit_length + 3) / 4); index++)
        {
            dest_hw[3 - index] = p_edit->edit_data[index];
        }
        if ((p_edit->edit_length % 4) != 0)
        {
            index = ((p_edit->edit_length + 3) / 4) - 1;
            dest_hw[3 - index] = dest_hw[3 - index]<<16;
        }
    }
    else
    {
        CTC_ERROR_DUMP(sys_usw_dword_reverse_copy(dest_hw, p_edit->edit_data, (p_edit->edit_length + 3) / 4));
    }
    field_id = EpePktProcFlexTunnelCtl_flexArray_0_flexHdrTemplate_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_A(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, &dest_hw);
    if (DRV_FROM_AT(lchip))
    {
        cmd = DRV_IOR(EpePktProcFlexTunnelCtl2_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_ctl2));
        field_id = EpePktProcFlexTunnelCtl2_flexArray_0_flexHdrTemplate_f + (profile_id - 1);
        DRV_SET_FIELD_A(lchip, EpePktProcFlexTunnelCtl2_t, field_id, &flex_ctl2, &dest_hw);
        cmd = DRV_IOW(EpePktProcFlexTunnelCtl2_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_ctl2));
    }

    for (index = 0; index < CTC_NH_UDF_MAX_EDIT_NUM; index++)
    {
        uint16 mask = 0;
        if (!p_edit->edit[index].type)
        {
            continue;
        }

        field_id = EpePktProcFlexTunnelCtl_flexArray_0_replaceTypeField1_f + index*SYS_NH_UDF_PROF_NUM + (profile_id-1)*field_step;
        DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, p_edit->edit[index].type);
        replacePos = (DRV_FROM_TMM(lchip) ? 128 : (p_edit->edit_length << 3)) - p_edit->edit[index].length-p_edit->edit[index].offset;
        field_id = EpePktProcFlexTunnelCtl_flexArray_0_replacePosField1_f + index*SYS_NH_UDF_PROF_NUM + (profile_id-1)*field_step;
        DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, (replacePos>>1));
        field_id = EpePktProcFlexTunnelCtl_flexArray_0_flexHdrMaskField1_f + index*SYS_NH_UDF_PROF_NUM + (profile_id-1)*field_step;

        mask = (1 << (p_edit->edit[index].length)) - 1;
        mask = ~mask;
        DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, mask);
    }
    cmd = DRV_IOW(EpePktProcFlexTunnelCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_ctl));

    CTC_BIT_SET(p_nh_master->udf_profile_bitmap, profile_id);
    p_nh_master->udf_ether_type[profile_id-1] = p_edit->ether_type;

    return CTC_E_NONE;
}

int32
_sys_usw_nh_remove_udf_profile(uint8 lchip, uint8 profile_id)
{
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint32 cmd = 0;
    EpePktProcFlexTunnelCtl_m flex_ctl;
    uint32 field_id = 0;
    uint8 field_step = 0;
    uint8 index = 0;

    if (!profile_id || profile_id > 8)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (p_nh_master->udf_profile_ref_cnt[profile_id-1])
    {
        return CTC_E_IN_USE;
    }

    cmd = DRV_IOR(EpePktProcFlexTunnelCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_ctl));

    field_step = (EpePktProcFlexTunnelCtl_flexArray_1_existIpHeader_f - EpePktProcFlexTunnelCtl_flexArray_0_existIpHeader_f);
    field_id = EpePktProcFlexTunnelCtl_flexArray_0_existIpHeader_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, 0);

    field_id = EpePktProcFlexTunnelCtl_flexArray_0_flexHdrLen_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, 0);

    field_id = EpePktProcFlexTunnelCtl_flexArray_0_l4HdrType_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, 0);

    field_id = EpePktProcFlexTunnelCtl_flexArray_0_lenFieldDeltaValue_f + (profile_id-1)*field_step;
    DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, 0);

    for (index = 0; index < CTC_NH_UDF_MAX_EDIT_NUM; index++)
    {
        field_id = EpePktProcFlexTunnelCtl_flexArray_0_replaceTypeField1_f + index*SYS_NH_UDF_PROF_NUM + (profile_id-1)*field_step;
        DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, 0);
        field_id = EpePktProcFlexTunnelCtl_flexArray_0_replacePosField1_f + index*SYS_NH_UDF_PROF_NUM + (profile_id-1)*field_step;
        DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, 0);
        field_id = EpePktProcFlexTunnelCtl_flexArray_0_flexHdrMaskField1_f + index*SYS_NH_UDF_PROF_NUM + (profile_id-1)*field_step;
        DRV_SET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl, 0);
    }
    cmd = DRV_IOW(EpePktProcFlexTunnelCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_ctl));

    CTC_BIT_UNSET(p_nh_master->udf_profile_bitmap, profile_id);

    return CTC_E_NONE;
}

int32
_sys_usw_nh_get_udf_profile(uint8 lchip, ctc_nh_udf_profile_param_t* p_edit)
{
    uint32 cmd = 0;
    EpePktProcFlexTunnelCtl_m flex_ctl;
    uint8 field_step = 0;
    uint32 value = 0;
    uint32 field_id = 0;
    uint8 profile_id = 0;

    CTC_MAX_VALUE_CHECK(p_edit->profile_id, SYS_NH_UDF_PROF_NUM);
    if (!CTC_IS_BIT_SET(g_usw_nh_master[lchip]->udf_profile_bitmap, p_edit->profile_id))
    {
        return CTC_E_NOT_EXIST;
    }

    profile_id = p_edit->profile_id-1;

    cmd = DRV_IOR(EpePktProcFlexTunnelCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &flex_ctl));
    field_step = (EpePktProcFlexTunnelCtl_flexArray_1_existIpHeader_f - EpePktProcFlexTunnelCtl_flexArray_0_existIpHeader_f);
    field_id = EpePktProcFlexTunnelCtl_flexArray_0_existIpHeader_f + profile_id*field_step;

    value = DRV_GET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl);
    if (value)
    {
        field_id = EpePktProcFlexTunnelCtl_flexArray_0_l4HdrType_f + profile_id*field_step;
        value = DRV_GET_FIELD_V(lchip, EpePktProcFlexTunnelCtl_t, field_id, &flex_ctl);
        if (value == 1)
        {
            p_edit->offset_type = CTC_NH_UDF_OFFSET_TYPE_UDP;
        }
        else if (value == 2)
        {
            p_edit->offset_type = CTC_NH_UDF_OFFSET_TYPE_GRE;
        }
        else if (value == 3)
        {
            p_edit->offset_type = CTC_NH_UDF_OFFSET_TYPE_GRE_WITH_KEY;
        }
        else
        {
            p_edit->offset_type = CTC_NH_UDF_OFFSET_TYPE_IP;
        }

    }
    else
    {
        p_edit->offset_type = CTC_NH_UDF_OFFSET_TYPE_RAW;
    }

    return CTC_E_NONE;
}

#define _________api___________
/**
 @brief This function is to create normal bridge nexthop in different types

 @param[in] gport, global port id

 @param[in] nh_type, nexthop type

 @return CTC_E_XXX
 */
int32
_sys_usw_brguc_nh_create_by_type(uint8 lchip, uint32 gport, sys_nh_param_brguc_sub_type_t nh_type)
{
    sys_nh_param_brguc_t brguc_nh;
    sys_hbnh_brguc_node_info_t* p_brguc_node;
    sys_hbnh_brguc_node_info_t brguc_node_tmp;
    bool is_add = FALSE;
	int32 ret = 0;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "gport = 0x%x , nh_type = %d\n", gport, nh_type);


    sal_memset(&brguc_nh, 0, sizeof(sys_nh_param_brguc_t));
    brguc_nh.hdr.nh_param_type = SYS_NH_TYPE_BRGUC;
    brguc_nh.hdr.nhid = SYS_NH_INVALID_NHID;
    brguc_nh.hdr.is_internal_nh = TRUE;
    brguc_nh.nh_sub_type = nh_type;
    brguc_nh.gport = gport;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "CtcGport = 0x%x ,DrvGport:0x%x, nh_type = %d, index:%d\n",
                                          gport, SYS_MAP_CTC_GPORT_TO_DRV_GPORT(gport), nh_type, GPORT_TO_INDEX(gport));

    brguc_node_tmp.gport = gport;
    p_brguc_node = ctc_hash_lookup(p_usw_nh_api_master[lchip]->brguc_info.brguc_hash, &brguc_node_tmp);
    if (NULL == p_brguc_node)
    {
        p_brguc_node = (sys_hbnh_brguc_node_info_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_hbnh_brguc_node_info_t));
        if (NULL == p_brguc_node)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
			return CTC_E_NO_MEMORY;

        }

        sal_memset(p_brguc_node, 0, sizeof(sys_hbnh_brguc_node_info_t));
        p_brguc_node->gport = gport;
        p_brguc_node->nhid_brguc  = SYS_NH_INVALID_NHID;
        p_brguc_node->nhid_bypass  = SYS_NH_INVALID_NHID;
        is_add = TRUE;
    }

    if ((nh_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BASIC)
        && (p_brguc_node->nhid_brguc != SYS_NH_INVALID_NHID))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Entry already exist \n");
		return CTC_E_EXIST;
    }

    if ((nh_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BYPASS)
        && (p_brguc_node->nhid_bypass != SYS_NH_INVALID_NHID))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Entry already exist \n");
		return CTC_E_EXIST;
    }

    ret = sys_usw_nh_api_create(lchip, (sys_nh_param_com_t*)(&brguc_nh));
	if(ret != CTC_E_NONE)
    {
        mem_free(p_brguc_node);
		return ret;
    }
    if (nh_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BASIC)
    {
        p_brguc_node->nhid_brguc = brguc_nh.hdr.nhid;
    }

    if (nh_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BYPASS)
    {
        p_brguc_node->nhid_bypass = brguc_nh.hdr.nhid;
    }

    if (is_add)
    {
        if (NULL == ctc_hash_insert(p_usw_nh_api_master[lchip]->brguc_info.brguc_hash, p_brguc_node))
        {
            if (p_brguc_node->nhid_brguc != SYS_NH_INVALID_NHID)
            {
                sys_usw_nh_api_delete(lchip, p_brguc_node->nhid_brguc, SYS_NH_TYPE_BRGUC);
            }

            if (p_brguc_node->nhid_bypass != SYS_NH_INVALID_NHID)
            {
                sys_usw_nh_api_delete(lchip, p_brguc_node->nhid_bypass, SYS_NH_TYPE_BRGUC);
            }

            mem_free(p_brguc_node);
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
			return CTC_E_NO_MEMORY;

        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_get_port(uint8 lchip, uint32 nhid, uint8* aps_en, uint32* gport)
{
    sys_nh_info_dsnh_t dsnh_info;
    sys_nh_info_com_t* p_nh_com_info= NULL;
    uint8 gchip = 0;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    sys_usw_get_gchip_id(lchip, &gchip);
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, (sys_nh_info_com_t**)&p_nh_com_info));
    if (CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_MCAST_PROFILE))
    {
        *gport = CTC_MAP_LPORT_TO_GPORT(gchip, 0);
        return CTC_E_NONE;
    }

    sal_memset(&dsnh_info, 0, sizeof(sys_nh_info_dsnh_t));
    CTC_ERROR_RETURN(_sys_usw_nh_get_nhinfo(lchip, nhid, &dsnh_info));
    *aps_en = dsnh_info.aps_en;
    *gport = ((dsnh_info.drop_pkt && !dsnh_info.use_destmap_profile) || dsnh_info.nh_entry_type == SYS_NH_TYPE_MCAST)?CTC_MAX_UINT16_VALUE:dsnh_info.gport;
    if (dsnh_info.is_mcast && (dsnh_info.nh_entry_type == SYS_NH_TYPE_MPLS))
    {
        *aps_en = 1;
    }

    if (dsnh_info.nh_entry_type == SYS_NH_TYPE_MPLS)
    {
        sys_nh_info_mpls_t* p_mpls_info = NULL;
        p_mpls_info = (sys_nh_info_mpls_t*)p_nh_com_info;
         *aps_en = p_mpls_info->aps_xcon_met ? 1:*aps_en;

    }
    else if (dsnh_info.nh_entry_type == SYS_NH_TYPE_APS)
    {
        sys_nh_info_aps_t* p_aps_info = NULL;
        p_aps_info = (sys_nh_info_aps_t*)p_nh_com_info;
         *aps_en = p_aps_info->aps_xcon_met ?1:*aps_en;
    }
    return CTC_E_NONE;
}

bool
sys_usw_nh_is_cpu_nhid(uint8 lchip, uint32 nhid)
{
    uint8 is_cpu_nh = 0;
    int32 ret = 0;
    sys_nh_info_com_t* p_nhinfo = NULL;
    sys_nh_info_misc_t* p_nh_misc_info = NULL;

    if (nhid == SYS_NH_RESOLVED_NHID_FOR_TOCPU)
    {
        is_cpu_nh = 1;
    }

    ret = sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo);
    if (ret < 0)
    {
        return FALSE;
    }

    if ((p_nhinfo) && (p_nhinfo->hdr.nh_entry_type == SYS_NH_TYPE_MISC))
    {
        p_nh_misc_info = (sys_nh_info_misc_t*)p_nhinfo;
        if (p_nh_misc_info->misc_nh_type == CTC_MISC_NH_TYPE_TO_CPU)
        {
            is_cpu_nh = 1;
        }
    }
    return (is_cpu_nh ? TRUE : FALSE);
}

int32
_sys_usw_nh_info_free(uint8 lchip, uint32 nhid)
{
    sys_usw_opf_t opf;
    sys_nh_info_com_t* p_nhinfo = NULL;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    sys_nh_info_com_t nh_temp;
    sys_nh_info_ext_t* p_nhinfo_ext = NULL;
    sys_nh_info_ext_t nh_temp_ext;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    sal_memset(&nh_temp, 0, sizeof(nh_temp));

    if (nhid >= p_nh_master->max_external_nhid)
    {
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_NHID_INTERNAL;
        CTC_ERROR_RETURN(sys_usw_opf_free_offset(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, 1, nhid));
        p_nh_master->internal_nh_used_num = p_nh_master->internal_nh_used_num?(p_nh_master->internal_nh_used_num-1):0;
    }

    nh_temp.hdr.nh_id = nhid;
    p_nhinfo = (sys_nh_info_com_t*)ctc_hash_remove(p_nh_master->nhid_hash, &nh_temp);
    if (p_nhinfo)
    {
        mem_free(p_nhinfo);
    }
    nh_temp_ext.nh_id = nhid;
    p_nhinfo_ext = (sys_nh_info_ext_t*)ctc_hash_remove(p_nh_master->nhid_ext_hash, &nh_temp_ext);
    if (p_nhinfo_ext)
    {
        mem_free(p_nhinfo_ext);
    }


    return CTC_E_NONE;
}

int32
_sys_usw_nh_get_nhinfo(uint8 lchip, uint32 nhid, sys_nh_info_dsnh_t* p_nhinfo)
{

    sys_nh_info_com_t* p_nh_com_info = NULL;
    sys_l3if_ecmp_if_t ecmp_if = {0};
    uint8   gchip  = 0;
    uint32   arp_id = 0;
    uint32   tmp = 0;
    uint32 dest_id = 0;
    uint8  dest_chipid = 0;
    sys_nh_db_arp_t *p_arp = NULL;
    sys_nh_info_bind_t* bind_data = NULL;
    int32 ret = 0;
    uint16 loop = 0;

    if (!p_nhinfo)
    {
        return CTC_E_NONE;
    }

    CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, (sys_nh_info_com_t**)&p_nh_com_info), ret, error_proc);
    if ((p_nh_com_info->hdr.nh_entry_flags & SYS_NH_INFO_FLAG_MCAST_PROFILE))
    {
        /*mcast profile do not used by fwd */
        ret = CTC_E_INVALID_PARAM;
        goto error_proc;
    }

    sys_usw_get_gchip_id(lchip, &gchip);

    p_nhinfo->nhid = nhid;
    p_nhinfo->nh_entry_type = p_nh_com_info->hdr.nh_entry_type;
    p_nhinfo->nh_entry_flags = p_nh_com_info->hdr.nh_entry_flags;
    p_nhinfo->aps_en        = CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN);
    p_nhinfo->drop_pkt      = CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV);
    p_nhinfo->dsnh_offset   = p_nh_com_info->hdr.dsnh_ptr?
                                                          p_nh_com_info->hdr.dsnh_ptr : p_nh_com_info->hdr.dsnh_offset;
    p_nhinfo->nexthop_ext   = CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
    p_nhinfo->dsfwd_valid   = CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD)
                               || (p_nh_com_info->hdr.nh_entry_flags & SYS_NH_INFO_FLAG_HAVE_RSV_DSFWD);

    p_nhinfo->dsfwd1_valid   = DRV_FROM_AT(lchip)&&(CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1)
                               || (p_nh_com_info->hdr.nh_entry_flags & SYS_NH_INFO_FLAG_HAVE_RSV_DSFWD));
    if (CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE))
    {
        p_nhinfo->bypass_igr_edit= 1;
    }

    p_nhinfo->merge_dsfwd = 0;
    if(!p_nhinfo->dsfwd_valid)
    {
        /*Use DsFwd Mode*/
        if (CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_ECMP_IF))
        {
            p_nhinfo->merge_dsfwd = 1;
        }

    }
    else
    {
        p_nhinfo->dsfwd_offset = p_nh_com_info->hdr.dsfwd_offset;
    }
    p_nhinfo->dsfwd1_offset = p_nh_com_info->hdr.dsfwd1_offset;

    switch (p_nh_com_info->hdr.nh_entry_type)
    {
    case SYS_NH_TYPE_MCAST:
        {
            sys_nh_info_mcast_t * p_nh_mcast_info = (sys_nh_info_mcast_t*)p_nh_com_info;
            p_nhinfo->is_mcast = 1;
            p_nhinfo->merge_dsfwd = 1;
            p_nhinfo->gport = ((p_nh_mcast_info->basic_met_offset >> g_usw_nh_master[lchip]->met_mode)&0xffff);
            dest_id = ((p_nh_mcast_info->basic_met_offset >> g_usw_nh_master[lchip]->met_mode)&0xffff);
            if(CTC_FLAG_ISSET(p_nh_mcast_info->mcast_flag, SYS_NH_INFO_MCAST_FLAG_LOGIC_REP_LIST_EN))
            {
                p_nhinfo->logic_rep_list = 1;
                p_nhinfo->logic_rep_num = p_nh_mcast_info->physical_replication_num;
            }
        }
        break;
    case SYS_NH_TYPE_BRGUC:
        {
            sys_nh_info_brguc_t* p_nh_brguc_info = (sys_nh_info_brguc_t*)p_nh_com_info;

            if (!p_nhinfo->aps_en)
            {
                p_nhinfo->gport   = p_nh_brguc_info->dest_gport;
                dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_brguc_info->dest_gport);
                dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_brguc_info->dest_gport);
            }
            else
            {
                p_nhinfo->gport  = p_nh_brguc_info->dest_gport;
                dest_chipid            = gchip;
                dest_id                 = p_nh_brguc_info->dest_gport;
                p_nhinfo->individual_nexthop =
                    CTC_FLAG_ISSET(p_nh_brguc_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_SHARE_DSNH)? 0 : 1;
                if (p_nhinfo->protection_path && p_nhinfo->individual_nexthop)
                {
                    p_nhinfo->dsnh_offset = p_nhinfo->dsnh_offset + (p_nhinfo->nexthop_ext?2:1);
                }
            }

            if (!p_nhinfo->dsfwd_valid)
            {
                p_nhinfo->merge_dsfwd  = 1; /*L2Uc Nexthop don't need update,so it can use merge DsFwd mode*/
            }

            if (p_nh_brguc_info->nh_sub_type < SYS_NH_PARAM_BRGUC_SUB_TYPE_VLAN_EDIT)
            {
                /*indicate l2uc*/
                p_nhinfo->re_route = 1;
            }

           if ((p_nh_brguc_info->flag & SYS_NH_BRGUC_LOOP_NH) && g_usw_nh_master[lchip]->rsv_nh_ptr)
            {
              p_nhinfo->dsnh_offset = g_usw_nh_master[lchip]->rsv_nh_ptr;
            }
        }
        break;

    case SYS_NH_TYPE_MPLS:
        {
            sys_nh_info_mpls_t* p_nh_mpls_info = (sys_nh_info_mpls_t*)p_nh_com_info;
            sys_nh_db_mpls_tunnel_t* p_mpls_tunnel = NULL;
            bind_data = p_nh_mpls_info->pd->bind_data;
            if (!p_nhinfo->aps_en)
            {
                p_nhinfo->gport       = p_nh_mpls_info->gport;
                dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_mpls_info->gport);
                dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_mpls_info->gport);
                arp_id =              p_nh_mpls_info->arp_id;
            }
            else
            {
                dest_chipid           = gchip;
                dest_id               = p_nh_mpls_info->gport;
                p_nhinfo->gport       = p_nh_mpls_info->gport;
                p_nhinfo->individual_nexthop = 0;
                p_nhinfo->is_mcast = p_nh_mpls_info->aps_xcon_met;
                p_nhinfo->use_destmap_profile = p_nh_mpls_info->arp_id ? 1:0;
                arp_id = 0;
                if (p_nh_mpls_info->aps_xcon_met )
                {
                    if (p_nh_mpls_info->met_offset)
                    {
                        dest_id = p_nh_mpls_info->met_offset;
                    }
                    else
                    {
                        sys_usw_aps_get_met(lchip,  p_nh_mpls_info->gport, &tmp, NULL);
                        dest_id = tmp;
                    }
                    p_nhinfo->merge_dsfwd  = 2;
                    p_nhinfo->aps_en = 0;
                    if (p_nhinfo->oam_nh)
                    {

                        /*for oam tx, do not using mcast flow*/
                        p_nhinfo->gport       = p_nh_mpls_info->gport;
                        arp_id = p_nh_mpls_info->arp_id;
                        dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_mpls_info->gport);
                        dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_mpls_info->gport);
                        p_nhinfo->is_mcast    = 0;
                    }
                }
            }

            CTC_ERROR_DUMP(sys_usw_nh_lkup_mpls_tunnel(lchip, p_nh_mpls_info->tunnel_id, &p_mpls_tunnel));
            if (p_mpls_tunnel && p_mpls_tunnel->sr_loop_num)
            {
                p_nhinfo->gport       = p_mpls_tunnel->gport;
                arp_id = 0;
                dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_mpls_tunnel->gport);
                dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_mpls_tunnel->gport);
            }
            p_nhinfo->mep_on_tunnel = 0;
            if (!CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L3EDIT))/*LSP nexthop*/
            {
                if (!(p_mpls_tunnel && CTC_FLAG_ISSET(p_mpls_tunnel->flag, SYS_NH_MPLS_TUNNEL_FLAG_EXSIT_SPME)
                    && CTC_FLAG_ISSET(p_mpls_tunnel->flag, SYS_NH_MPLS_TUNNEL_FLAG_APS)))
                {
                    p_nhinfo->mep_on_tunnel = p_nhinfo->aps_en;
                }
            }
            p_nhinfo->oam_aps_en = CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN);
            p_nhinfo->oam_aps_group_id = (p_mpls_tunnel)? p_mpls_tunnel->gport : 0;

            p_nhinfo->tunnel_id = p_mpls_tunnel?p_mpls_tunnel->tunnel_id:0;
            p_nhinfo->adjust_len = p_nh_mpls_info->adjust_len;

        }
        break;
    case SYS_NH_TYPE_ECMP:
        {
            sys_nh_info_ecmp_t* p_nh_ecmp_info = (sys_nh_info_ecmp_t*)p_nh_com_info;
            p_nhinfo->ecmp_valid = TRUE;
            p_nhinfo->ecmp_group_id = p_nh_ecmp_info->ecmp_group_id;
            p_nhinfo->ecmp_num = p_nh_ecmp_info->ecmp_cnt;
            p_nhinfo->ecmp_cnt = p_nh_ecmp_info->ecmp_cnt;
            p_nhinfo->valid_cnt = p_nh_ecmp_info->valid_cnt;
            p_nhinfo->h_ecmp_en = p_nh_ecmp_info->h_ecmp_en;
            p_nhinfo->merge_dsfwd  = 0;
            p_nhinfo->rpf_profile_id  = p_nh_ecmp_info->rpf_id;

            if(p_nhinfo->nh_array)
            {
                 for (loop = 0; loop <  p_nh_ecmp_info->ecmp_cnt && loop < CTC_MAX_ECPN ; loop++)
                 {
                      p_nhinfo->nh_array[loop] = p_nh_ecmp_info->nh_array[loop];
                 }
            }
       }
       break;
    case SYS_NH_TYPE_IPUC:
        {
            sys_nh_info_ipuc_t* p_nh_ipuc_info = (sys_nh_info_ipuc_t*)p_nh_com_info;
            bind_data = p_nh_ipuc_info->pd->bind_data;
            p_nhinfo->have_l2edit = CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDIT);
            p_nhinfo->replace_mode = CTC_FLAG_ISSET(p_nh_ipuc_info->flag, SYS_NH_IPUC_FLAG_REPLACE_MODE_EN);
            if (!p_nhinfo->aps_en)
            {
                p_nhinfo->gport       = p_nh_ipuc_info->gport;
                arp_id = p_nh_ipuc_info->arp_id;
                dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_ipuc_info->gport);
                dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_ipuc_info->gport);
            }
            else
            {
                p_nhinfo->gport       = p_nh_ipuc_info->gport;
                dest_chipid           = gchip;
                dest_id               = p_nh_ipuc_info->gport;
                p_nhinfo->individual_nexthop =
                    CTC_FLAG_ISSET(p_nh_ipuc_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_SHARE_DSNH)? 0 : 1;
                if (p_nhinfo->protection_path && p_nhinfo->individual_nexthop)
                {
                    p_nhinfo->dsnh_offset = p_nhinfo->dsnh_offset + (p_nhinfo->nexthop_ext?2:1);
                }
            }
            p_nhinfo->merge_dsfwd = CTC_FLAG_ISSET(p_nh_ipuc_info->flag,SYS_NH_IPUC_FLAG_MERGE_DSFWD)?1:0;
            p_nhinfo->adjust_len = p_nh_ipuc_info->adjust_len;
            p_nhinfo->ldp_ext = p_nh_ipuc_info->ldp_ext;
        }
        break;

    case SYS_NH_TYPE_IP_TUNNEL:
        {
            sys_nh_info_ip_tunnel_t* p_nh_ip_tunnel_info = (sys_nh_info_ip_tunnel_t*)p_nh_com_info;
            bind_data = p_nh_ip_tunnel_info->bind_data;
            p_nhinfo->gport       = p_nh_ip_tunnel_info->gport;
            arp_id = p_nh_ip_tunnel_info->arp_id;
            p_nhinfo->is_ivi = CTC_FLAG_ISSET(p_nh_ip_tunnel_info->flag, SYS_NH_IP_TUNNEL_FLAG_IVI_6TO4) ||
                               CTC_FLAG_ISSET(p_nh_ip_tunnel_info->flag, SYS_NH_IP_TUNNEL_FLAG_IVI_4TO6);
            p_nhinfo->re_route = CTC_FLAG_ISSET(p_nh_ip_tunnel_info->flag, SYS_NH_IP_TUNNEL_REROUTE);
            p_nhinfo->cloud_sec_en = (p_nh_ip_tunnel_info->dot1ae_en && (!DRV_FROM_TMM(lchip)))? 1 : 0;/*For TMM, cloud sec not from forward table */

            if (CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_ECMP_IF))
            {
                p_nhinfo->ecmp_valid = FALSE;
                p_nhinfo->is_ecmp_intf = TRUE;
                p_nhinfo->merge_dsfwd = 1;
                CTC_ERROR_RETURN(sys_usw_l3if_get_ecmp_if_info(lchip, p_nh_ip_tunnel_info->l3ifid, &ecmp_if));
                p_nhinfo->ecmp_group_id = ecmp_if.hw_group_id;
                dest_id = p_nhinfo->ecmp_group_id;
            }
            else
            {
                dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_ip_tunnel_info->gport);
                dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_ip_tunnel_info->gport);
            }
            p_nhinfo->logic_port = p_nh_ip_tunnel_info->dest_logic_port;
            p_nhinfo->bind_ldp = p_nh_ip_tunnel_info->bind_ldp;
            p_nhinfo->adjust_len = p_nh_ip_tunnel_info->adjust_len;
        }
        break;

    case SYS_NH_TYPE_TRILL:
        {
            sys_nh_info_trill_t* p_nh_trill_info = (sys_nh_info_trill_t*)p_nh_com_info;
            bind_data = p_nh_trill_info->bind_data;
            p_nhinfo->gport       = p_nh_trill_info->gport;
            dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_trill_info->gport);
            dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_trill_info->gport);
        }
        break;

    case SYS_NH_TYPE_DROP:
        {
            p_nhinfo->dsfwd_valid = TRUE;
            p_nhinfo->drop_pkt = TRUE;
            dest_chipid           = gchip;
            dest_id               = SYS_RSV_PORT_DROP_ID;
            p_nhinfo->gport       = CTC_MAP_LPORT_TO_GPORT(dest_chipid, dest_id);
        }
    break;

    case SYS_NH_TYPE_TOCPU:
        {
            sys_cpu_reason_dest_info_t dest_info;
            sal_memset(&dest_info, 0, sizeof(dest_info));

            p_nhinfo->gport = CTC_GPORT_RCPU(gchip);
            p_nhinfo->dsfwd_valid = TRUE;
            dest_chipid           = gchip;

            /*Notice: the function may be called in Qos module, to avoid dead lock, using internal function instead*/
            CTC_ERROR_RETURN(_sys_usw_cpu_reason_get_info(lchip, CTC_PKT_CPU_REASON_FWD_CPU, &dest_info));
            p_nhinfo->dest_map = dest_info.dest_map;
            return CTC_E_NONE;
        }
        break;
    case SYS_NH_TYPE_MISC:
        {
            sys_nh_info_misc_t* p_nh_misc_info = (sys_nh_info_misc_t*)p_nh_com_info;
            bind_data = p_nh_misc_info->bind_data;

            p_nhinfo->gport       = p_nh_misc_info->gport;
            p_nhinfo->swap_mac    = CTC_FLAG_ISSET(p_nh_misc_info->flag, CTC_MISC_NH_FLEX_EDIT_SWAP_MACDA);
            dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_misc_info->gport);
            dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_misc_info->gport);
            if (p_nh_misc_info->misc_nh_type == CTC_MISC_NH_TYPE_TO_CPU)
            {
                sys_cpu_reason_dest_info_t dest_info;
                sal_memset(&dest_info, 0, sizeof(dest_info));

                dest_id = CTC_PKT_CPU_REASON_GET_BY_NHPTR(p_nhinfo->dsnh_offset);
                CTC_ERROR_RETURN(_sys_usw_cpu_reason_get_info(lchip, dest_id, &dest_info));
                p_nhinfo->dest_map = dest_info.dest_map;
                _sys_usw_nh_get_reason_nhinfo(lchip, &dest_info, dest_id, &p_nhinfo->dsnh_offset, &p_nhinfo->nexthop_ext);
                p_nhinfo->to_cpu_en = CTC_IS_CPU_PORT(p_nhinfo->gport)? 1 : 0;
                return CTC_E_NONE;
             }
        }
        break;

    case SYS_NH_TYPE_ILOOP:
        {
            sys_nh_info_special_t* p_nh_iloop_info = (sys_nh_info_special_t *)p_nh_com_info;
            p_nhinfo->dsfwd_valid   = CTC_FLAG_ISSET(p_nh_iloop_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD);
            p_nhinfo->nexthop_ext   = CTC_FLAG_ISSET(p_nh_iloop_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
            p_nhinfo->aps_en        = CTC_FLAG_ISSET(p_nh_iloop_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN);
            dest_chipid             = gchip;
            dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_iloop_info->dest_gport);
            p_nhinfo->gport       = p_nh_iloop_info->dest_gport;
        }
        break;

    case SYS_NH_TYPE_RSPAN:
        break;
    case SYS_NH_TYPE_WLAN_TUNNEL:
        {
            sys_nh_info_wlan_tunnel_t* p_nh_wlan_tunnel_info = (sys_nh_info_wlan_tunnel_t*)p_nh_com_info;

            p_nhinfo->gport       = p_nh_wlan_tunnel_info->gport;
            dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_wlan_tunnel_info->gport);
            dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_wlan_tunnel_info->gport);
        }
        break;
    case SYS_NH_TYPE_SRV6:
        {
            sys_nh_info_srv6_t* p_nh_srv6_info = (sys_nh_info_srv6_t*)p_nh_com_info;
            sys_nh_db_srh_t    *p_srh_tnl = NULL;
            bind_data = p_nh_srv6_info->bind_data;
            p_srh_tnl = _sys_usw_nh_lkup_srh_id(lchip, p_nh_srv6_info->srh_id);
            p_nhinfo->gport       = p_nh_srv6_info->gport;
            arp_id                = ((NULL == p_srh_tnl) ||
            CTC_FLAG_ISSET(p_nh_srv6_info->flag, SYS_NH_SRV6_FLAG_REROUTE) ||
            CTC_FLAG_ISSET(p_nh_srv6_info->flag, SYS_NH_SRV6_FLAG_LOOP_NH)) ? 0 : p_srh_tnl->arp_id;
            if (!p_nhinfo->aps_en)
            {
                dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_srv6_info->gport);
                dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nh_srv6_info->gport);
            }
            else
            {
                dest_chipid           = gchip;
                dest_id               = p_nh_srv6_info->gport;
                arp_id = 0;
            }
            if (p_nh_srv6_info->ecmp_if_id)
            {
                p_nhinfo->ecmp_valid = FALSE;
                p_nhinfo->is_ecmp_intf = TRUE;
                p_nhinfo->merge_dsfwd = 1;
                p_nhinfo->ecmp_group_id = p_nh_srv6_info->ecmp_if_id;
                dest_id = p_nhinfo->ecmp_group_id;
            }
            p_nhinfo->tunnel_id = (0 != p_nh_srv6_info->srh_id)? p_nh_srv6_info->srh_id:SYS_COM_LDP_ECMP_ID(p_nhinfo->ecmp_group_id);
        }
        break;
    case SYS_NH_TYPE_OVERLAY_VNI:
        if(CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_PORT))
        {
            p_nhinfo->bind_ldp = 1;
        }
        break;
    case SYS_NH_TYPE_OVERLAY:
        {
            sys_nh_info_overlay_t* p_nh_overlay_info = (sys_nh_info_overlay_t*)p_nh_com_info;
            sys_nh_db_ol_tunnel_t* tunnel_db = NULL;
            sys_nh_info_dsnh_t p_vni_nhinfo;

            sal_memset(&p_vni_nhinfo,0,sizeof(sys_nh_info_dsnh_t));

            if (p_nh_overlay_info->nhid)/* get dsnh_offset from SYS_NH_TYPE_OVERLAY_VNI */
            {
                CTC_ERROR_RETURN(_sys_usw_nh_get_nhinfo(lchip, p_nh_overlay_info->nhid, &p_vni_nhinfo));
                p_nhinfo->dsnh_offset = p_vni_nhinfo.dsnh_offset;
                p_nhinfo->bind_ldp = p_vni_nhinfo.bind_ldp;
            }
            else
            {
                CTC_ERROR_RETURN(_sys_usw_nh_get_resolved_offset(lchip, SYS_NH_RES_OFFSET_TYPE_OL_BRIDGE_NH, &p_nhinfo->dsnh_offset));
            }

            p_nhinfo->nh_entry_type = SYS_NH_TYPE_OVERLAY;
            p_nhinfo->gport       = p_nh_overlay_info->gport;
            p_nhinfo->logic_port = p_nh_overlay_info->dest_logic_port;

            if (!p_nh_overlay_info->ecmp_gid || CTC_FLAG_ISSET(p_nh_overlay_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_ECMP_IF))
             {
                 tunnel_db = _sys_usw_nh_lkup_tunnel(lchip, p_nhinfo->logic_port);
                 arp_id = tunnel_db ? tunnel_db->arp_id : 0;
                 p_nhinfo->dsfwd1_offset = p_nh_overlay_info->hdr.dsfwd1_offset;
             }

            if (p_nh_overlay_info->ecmp_gid)
            {
                p_nhinfo->ecmp_valid = FALSE;
                p_nhinfo->is_ecmp_intf = tunnel_db? (tunnel_db->ul_nh_en == 0) : 1;
                p_nhinfo->merge_dsfwd = 1;
                p_nhinfo->ecmp_group_id = p_nh_overlay_info->ecmp_gid;
                dest_id = p_nhinfo->ecmp_group_id;

                if(!CTC_FLAG_ISSET(p_nh_overlay_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_ECMP_IF))
                {
                    p_nhinfo->logic_port = 0;
                }
            }
            else
            {
                dest_chipid           = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nhinfo->gport);
                dest_id               = SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_nhinfo->gport);
            }


        }
        break;
    case SYS_NH_TYPE_APS:
        {
            sys_nh_info_aps_t* p_nh_aps_info = (sys_nh_info_aps_t*)p_nh_com_info;
            sys_nh_info_com_t* p_w_nh_info = NULL;
            sys_nh_info_com_t* p_p_nh_info = NULL;
            uint8 aps_en = 0;
            uint32 tmp_gport = 0;
            bind_data = p_nh_aps_info->bind_data;
            CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_nh_aps_info->w_nexthop_id, (sys_nh_info_com_t**)&p_w_nh_info), ret, error_proc);
            p_nhinfo->gport = p_nh_aps_info->aps_group_id;
            dest_chipid           = gchip;
            dest_id               = p_nh_aps_info->aps_group_id;
            arp_id = 0;
            p_nhinfo->oam_aps_en = CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN);
            if (!p_nhinfo->protection_path)
            {
                p_nhinfo->mep_on_tunnel = CTC_FLAG_ISSET(p_w_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN)?0:1;
                sys_usw_nh_get_port(lchip, p_nh_aps_info->w_nexthop_id, &aps_en, &tmp_gport);
                p_nhinfo->oam_aps_group_id = CTC_FLAG_ISSET(p_w_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN)?tmp_gport:p_nh_aps_info->aps_group_id;
            }
            else
            {
                CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_nh_aps_info->p_nexthop_id, (sys_nh_info_com_t**)&p_p_nh_info), ret, error_proc);
                p_nhinfo->dsnh_offset = p_p_nh_info->hdr.dsnh_offset;
                sys_usw_nh_get_port(lchip, p_nh_aps_info->p_nexthop_id, &aps_en, &tmp_gport);
                p_nhinfo->mep_on_tunnel = CTC_FLAG_ISSET(p_p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN)?0:1;
                p_nhinfo->oam_aps_group_id = CTC_FLAG_ISSET(p_p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN)?tmp_gport:p_nh_aps_info->aps_group_id;
            }
            p_nhinfo->is_mcast = p_nh_aps_info->aps_xcon_met;
            if (p_nh_aps_info->aps_xcon_met && !p_nhinfo->oam_nh)
            {
                 sys_usw_aps_get_met( lchip, p_nh_aps_info->aps_group_id, &tmp, NULL);
                 dest_id = tmp;
                 p_nhinfo->merge_dsfwd  = 2;
            }
            if (DRV_FROM_AT(lchip))
            {
                p_nhinfo->merge_dsfwd  = 1;
            }
            p_nhinfo->use_destmap_profile = p_nh_aps_info->arp_num ? 1:0;
            p_nhinfo->w_nh_id = p_nh_aps_info->w_nexthop_id;
        }
        break;
    default:
        return CTC_E_INVALID_PARAM;
    }

    if (CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV))
    {
        arp_id = 0;
    }

    if (arp_id)
    {
        p_arp = (sys_usw_nh_lkup_arp_id(lchip, arp_id));
        if (NULL == p_arp)
        {
            return CTC_E_NOT_EXIST;
        }
        p_nhinfo->arp_id = arp_id;

        p_nhinfo->drop_pkt = CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_DROP);

        if (CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_PORT_VALID) &&
            !CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_DROP) &&
            !CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU))
        {
            p_nhinfo->gport = p_arp->gport;
        }

        p_nhinfo->to_cpu_en    = CTC_FLAG_ISSET(p_arp->flag, SYS_NH_ARP_FLAG_REDIRECT_TO_CPU)?1:0;
        /*If Using destmap profile, mapping profile id to destid for encoding destmap usage*/
        if (p_arp->destmap_profile)
        {
            p_nhinfo->use_destmap_profile = 1;
        }
    }

    if( p_nhinfo->is_mcast)
    {
        p_nhinfo->dest_map =SYS_ENCODE_MCAST_IPE_DESTMAP(dest_id);
        p_nhinfo->aps_en  = 0 ;
    }
    else if (arp_id)
    {  /*aps nexthop or  aps mpls ,arp_id = 0 */
        if(p_arp->destmap_profile )
        {
            p_nhinfo->dest_map = SYS_ENCODE_ARP_DESTMAP(p_arp->destmap_profile);
        }
        else if(p_nhinfo->to_cpu_en )
        {/*merge dsfwd */
            sys_cpu_reason_dest_info_t dest_info;
            sal_memset(&dest_info, 0, sizeof(dest_info));
            CTC_ERROR_RETURN(_sys_usw_cpu_reason_get_info(lchip, CTC_PKT_CPU_REASON_ARP_MISS, &dest_info));
            p_nhinfo->dest_map = dest_info.dest_map;
            p_nhinfo->dsnh_offset  =   CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_ARP_MISS, 0);
            p_nhinfo->gport = CTC_GPORT_RCPU((CTC_MAP_GPORT_TO_GCHIP(p_arp->gport)));
        }
       else
        {
            p_nhinfo->dest_map = SYS_ENCODE_DESTMAP(dest_chipid, dest_id);
        }
    }
    else if (CTC_IS_CPU_PORT(p_nhinfo->gport))
    {
        /* !SYS_NH_TYPE_MISC and !SYS_NH_TYPE_TOCPU  */
        /*fwd to cpu nexthop without arp, using CTC_PKT_CPU_REASON_FWD_CPU cpu reason*/
        sys_cpu_reason_dest_info_t dest_info;
        sal_memset(&dest_info, 0, sizeof(dest_info));
        CTC_ERROR_RETURN(_sys_usw_cpu_reason_get_info(lchip, CTC_PKT_CPU_REASON_FWD_CPU, &dest_info));
        p_nhinfo->dest_map = SYS_ENCODE_EXCP_DESTMAP_GCHIP(dest_chipid, dest_info.dest_map);
        p_nhinfo->dsnh_offset = CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_FWD_CPU, 0);
    }
    else if (p_nhinfo->drop_pkt)
    {
        p_nhinfo->dest_map = SYS_ENCODE_DESTMAP(gchip, SYS_RSV_PORT_DROP_ID);
        p_nhinfo->dsnh_offset = SYS_USW_DROP_NH_OFFSET;
    }
    else if(p_nhinfo->is_ecmp_intf)
    {
        p_nhinfo->dest_map = SYS_ENCODE_ECMP_DESTMAP(p_nhinfo->ecmp_group_id);
    }
    else if(p_nhinfo->aps_en)
    {
        p_nhinfo->dest_map = SYS_ENCODE_APS_DESTMAP(dest_chipid, dest_id);
    }
    else
    {
        p_nhinfo->dest_map = SYS_ENCODE_DESTMAP(dest_chipid, dest_id);
    }

    if (bind_data)
    {
        p_nhinfo->bind_feature = bind_data->bind_feature;
        p_nhinfo->bind_lchip = bind_data->bind_lchip;
        p_nhinfo->data = bind_data->data;
        p_nhinfo->updateAd = bind_data->updateAd;
        p_nhinfo->chk_data = bind_data->chk_data;
    }

    return CTC_E_NONE;
error_proc:
    return ret;
}

int32
sys_usw_nh_get_nhinfo_by_nhid(uint8 lchip, uint32 nhid, sys_nh_info_com_t** pp_nhinfo)
{
    sys_nh_info_com_t* p_nhinfo = NULL;
    sys_nh_info_com_t nh_temp;

    //sal_memset(&nh_temp, 0, sizeof(nh_temp));
    nh_temp.hdr.nh_id = nhid;
    p_nhinfo = ctc_hash_lookup(g_usw_nh_master[lchip]->nhid_hash, &nh_temp);
    if (NULL == p_nhinfo)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop] Nexthop %u not exist \n", nhid);
        return CTC_E_NOT_EXIST;
    }

    *pp_nhinfo = p_nhinfo;

    return CTC_E_NONE;
}

int32
sys_usw_nh_get_nhinfo_ext_by_nhid(uint8 lchip, uint32 nhid, sys_nh_info_ext_t** pp_nhinfo, uint8 with_alloc)
{
    sys_nh_info_ext_t* p_nh_info_ext = NULL;
    sys_nh_info_ext_t nh_temp;

    if (nhid < SYS_NH_RESOLVED_NHID_MAX)
    {
        *pp_nhinfo = NULL;
        return CTC_E_NONE;
    }

    sal_memset(&nh_temp, 0, sizeof(nh_temp));
    nh_temp.nh_id = nhid;
    p_nh_info_ext = ctc_hash_lookup(g_usw_nh_master[lchip]->nhid_ext_hash, &nh_temp);

    if ((NULL == p_nh_info_ext) && with_alloc)
    {
        p_nh_info_ext = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_info_ext_t));
        if (NULL == p_nh_info_ext)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_nh_info_ext, 0, sizeof(sys_nh_info_ext_t));
        p_nh_info_ext->nh_id = nhid;
        if (NULL == ctc_hash_insert(g_usw_nh_master[lchip]->nhid_ext_hash, p_nh_info_ext))
        {
            mem_free(p_nh_info_ext);
            return CTC_E_NO_MEMORY;
        }
    }

    *pp_nhinfo = p_nh_info_ext;

    return CTC_E_NONE;
}

int32
sys_usw_nh_free_nhinfo_ext_by_nhid(uint8 lchip, uint32 nhid)/*free sys_nh_info_ext_t when list empty!!!*/
{
    sys_nh_info_ext_t* p_nh_info_ext = NULL;
    sys_nh_info_ext_t nh_temp;
    sal_memset(&nh_temp, 0, sizeof(nh_temp));
    nh_temp.nh_id = nhid;
    p_nh_info_ext = ctc_hash_lookup(g_usw_nh_master[lchip]->nhid_ext_hash, &nh_temp);

    if (NULL == p_nh_info_ext)
    {
        return CTC_E_NONE;
    }
    if ((NULL == p_nh_info_ext->ecmp_list) && (NULL == p_nh_info_ext->aps_list))
    {
        nh_temp.nh_id = nhid;
        p_nh_info_ext = (sys_nh_info_ext_t*)ctc_hash_remove(g_usw_nh_master[lchip]->nhid_ext_hash, &nh_temp);
        if (p_nh_info_ext)
        {
            mem_free(p_nh_info_ext);
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_is_unrov(uint8 lchip, uint32 nhid, uint8* val)
{
    sys_nh_info_com_t* p_nhinfo = NULL;
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo));
    *val = CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV) ? 1 : 0;
    return CTC_E_NONE;
}

int32
sys_usw_nh_api_create(uint8 lchip, sys_nh_param_com_t* p_nh_com_para)
{
    sys_usw_nh_type_t nh_type;
    p_sys_nh_create_cb_t nh_sem_map_cb;
    sys_nh_info_com_t* p_nhinfo = NULL;
    int32 ret = CTC_E_NONE;
    uint32 tmp_nh_id = 0;
    uint32 db_entry_size = 0;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    p_sys_nh_delete_cb_t nh_del_cb;

    if (!p_nh_com_para->hdr.is_internal_nh
        && (p_nh_com_para->hdr.nh_param_type != SYS_NH_TYPE_DROP)
        && (p_nh_com_para->hdr.nh_param_type != SYS_NH_TYPE_TOCPU))
    {
        if (p_nh_com_para->hdr.nhid < SYS_NH_RESOLVED_NHID_MAX ||
            p_nh_com_para->hdr.nhid >= (p_nh_master->max_external_nhid))
        {
            return CTC_E_INVALID_PARAM;
        }
    }

    /*Check If this nexthop is exist*/
    if (!(p_nh_com_para->hdr.is_internal_nh))
    {
        sys_nh_info_com_t nh_temp;
        sal_memset(&nh_temp, 0, sizeof(nh_temp));
        nh_temp.hdr.nh_id = p_nh_com_para->hdr.nhid;
        if (ctc_hash_lookup(p_nh_master->nhid_hash, &nh_temp))
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop] Nexthop  exist \n");
            return CTC_E_EXIST;
        }
    }

    nh_type = p_nh_com_para->hdr.nh_param_type;
    db_entry_size = p_nh_master->db_size[nh_type];
    p_nhinfo = mem_malloc(MEM_NEXTHOP_MODULE, db_entry_size);
    if (NULL == p_nhinfo)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    else
    {
        sal_memset(p_nhinfo, 0, db_entry_size);
    }

    ret = _sys_usw_nh_alloc_offset_by_nhtype(lchip, p_nh_com_para, p_nhinfo);
    if (ret)
    {
        goto error0;
    }

    p_nhinfo->hdr.nh_id = p_nh_com_para->hdr.nhid;

    /*2. Semantic mapping Callback*/
    nh_sem_map_cb = p_nh_master->callbacks_nh_create[nh_type];
    nh_del_cb = p_nh_master->callbacks_nh_delete[nh_type];
    ret = (* nh_sem_map_cb)(lchip, p_nh_com_para, p_nhinfo);
    if (ret)
    {
        goto error1;
    }

    /*3. Store nh infor into nh_array*/
    if (p_nh_com_para->hdr.is_internal_nh)
    {
        /*alloc a new nhid*/
        sys_usw_opf_t opf;
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_NHID_INTERNAL;
        opf.multiple  = 1;
        opf.reverse = 0;

        if (p_nh_com_para->hdr.nh_param_type == SYS_NH_TYPE_OVERLAY_VNI &&
            CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE))
        {
            tmp_nh_id = SYS_NH_INTERNAL_NHID_OL_VNI_BASE + p_nhinfo->hdr.dsnh_offset;
            if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW))
            {
                CTC_BIT_SET(tmp_nh_id, SYS_USW_NH_DSNH_OFFSET_NO_HW_BIT) ;
            }
            ret = sys_usw_opf_alloc_offset_from_position(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, 1, tmp_nh_id);
        }
        else
        {
            ret = sys_usw_opf_alloc_offset(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, 1, &tmp_nh_id);
        }
        if (ret)
        {
            goto error2;
        }
        p_nh_com_para->hdr.nhid = tmp_nh_id; /*Write back the nhid*/
        p_nhinfo->hdr.nh_id = tmp_nh_id;
    }

    if (p_nh_com_para->hdr.is_internal_nh)
    {
        p_nh_master->internal_nh_used_num++;
    }

    if (NULL == ctc_hash_insert(p_nh_master->nhid_hash, p_nhinfo))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto error3;
    }

    if (ret == CTC_E_NONE && nh_type == SYS_NH_TYPE_ECMP)
    {
        sys_nh_info_ecmp_t* p_nhdb_ecmp = NULL;
        p_nhdb_ecmp = (sys_nh_info_ecmp_t*)p_nhinfo;
        if (p_nhdb_ecmp->h_ecmp_en && DRV_IS_TSINGMA(lchip))
        {
            p_nh_master->cur_ecmp_cnt += p_nh_master->hecmp_mem_num;
        }
        else
        {
            p_nh_master->cur_ecmp_cnt++;
        }
    }
    p_nh_master->nhid_used_cnt[nh_type]++;


    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM, 1);

    return CTC_E_NONE;


error3:
    _sys_usw_nh_info_free(lchip, p_nh_com_para->hdr.nhid);
error2:
    (* nh_del_cb)(lchip, p_nhinfo, p_nh_com_para);
error1:
    _sys_usw_nh_free_offset_by_nhinfo(lchip, nh_type, p_nhinfo);
error0:
    mem_free(p_nhinfo);

    return ret;
}

int32
sys_usw_nh_api_delete(uint8 lchip, uint32 nhid, sys_usw_nh_type_t nhid_type)
{
    p_sys_nh_delete_cb_t nh_del_cb;
    sys_usw_nh_type_t nh_type;
    sys_nh_info_com_t* p_nh_info = NULL;
    int32 ret = CTC_E_NONE;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint8  hecmp_mem = 1;
    sys_nh_param_com_t p_nh_com_para;

    sal_memset(&p_nh_com_para, 0, sizeof(p_nh_com_para));
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info));
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_ext_by_nhid(lchip, nhid, &(p_nh_com_para.hdr.p_nh_info_ext), 0));

    if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED) || (p_nh_com_para.hdr.p_nh_info_ext && p_nh_com_para.hdr.p_nh_info_ext->aps_list))
    {
        return CTC_E_IN_USE;
    }

    nh_type = p_nh_info->hdr.nh_entry_type;
    if ((nhid_type != p_nh_info->hdr.nh_entry_type))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Nexthop type  mismatch \n");
        return CTC_E_INVALID_CONFIG;
    }

    if (nh_type == SYS_NH_TYPE_ECMP)
    {
        sys_nh_info_ecmp_t* p_nhdb_ecmp = NULL;
        p_nhdb_ecmp = (sys_nh_info_ecmp_t*)p_nh_info;
        if (p_nhdb_ecmp->h_ecmp_en && DRV_IS_TSINGMA(lchip))
        {
            hecmp_mem = p_nh_master->hecmp_mem_num;
        }
    }

    nh_del_cb = p_nh_master->callbacks_nh_delete[nh_type];

    ret = (* nh_del_cb)(lchip, p_nh_info, &p_nh_com_para);

    ret = ret ? ret : _sys_usw_nh_free_offset_by_nhinfo(lchip, nh_type, p_nh_info);

    ret = ret ? ret : _sys_usw_nh_info_free(lchip, nhid);

    if (ret == CTC_E_NONE && nh_type == SYS_NH_TYPE_ECMP)
    {
        p_nh_master->cur_ecmp_cnt = (p_nh_master->cur_ecmp_cnt >= hecmp_mem) ? (p_nh_master->cur_ecmp_cnt - hecmp_mem) : p_nh_master->cur_ecmp_cnt;
    }
    if(p_nh_master->nhid_used_cnt[nh_type] && !ret)
    {
      p_nh_master->nhid_used_cnt[nh_type]--;
    }
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM, 1);
    return ret;
}
int32
sys_usw_nh_set_dirty_flag(uint8 lchip, uint32 nhid, uint8 set)
{
    sys_nh_info_com_t* p_nh_info;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info));
    if(set)
    {
        CTC_SET_FLAG(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DIRTY);
    }
    else
    {
        CTC_UNSET_FLAG(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DIRTY);
    }
    return CTC_E_NONE;
}
int32
sys_usw_nh_ol_tunnel_set_dirty_flag(uint8 lchip, uint32 ldp, uint8 is_set)
{
    sys_nh_db_ol_tunnel_t* p_ol_tunnel = NULL;

    p_ol_tunnel = _sys_usw_nh_lkup_tunnel(lchip, ldp);
    if(NULL == p_ol_tunnel)
    {
        return CTC_E_NOT_EXIST;
    }
    if(is_set)
    {
        CTC_SET_FLAG(p_ol_tunnel->flag, SYS_NH_OL_TUNNEL_DIRTY);
    }
    else
    {
        CTC_UNSET_FLAG(p_ol_tunnel->flag, SYS_NH_OL_TUNNEL_DIRTY);
    }
    return CTC_E_NONE;
}
int32
sys_usw_nh_check_dirty(uint8 lchip, uint32 nhid)
{
    sys_nh_info_com_t* p_nh_info = NULL;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info));

    /*1. check nh is dirty*/
    if(CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DIRTY))
    {
        return CTC_E_HW_BUSY;
    }

    /*2. check overlay tunnel is dirty*/
    if(p_nh_info->hdr.nh_entry_type == SYS_NH_TYPE_OVERLAY )
    {
        sys_nh_db_ol_tunnel_t* p_ol_tunnel = NULL;
        sys_nh_info_overlay_t* p_nh_overlay_info = (sys_nh_info_overlay_t*)p_nh_info;
        p_ol_tunnel = _sys_usw_nh_lkup_tunnel(lchip, p_nh_overlay_info->dest_logic_port);

        if(p_ol_tunnel && CTC_FLAG_ISSET(p_ol_tunnel->flag, SYS_NH_OL_TUNNEL_DIRTY))
        {
            return CTC_E_HW_BUSY;
        }
    }

    if(DRV_IS_TSINGMA(lchip) && g_usw_nh_master[lchip]->bind_ldp &&
                    p_nh_info->hdr.nh_entry_type == SYS_NH_TYPE_IP_TUNNEL)
    {
        sys_nh_db_ol_tunnel_t* p_ol_tunnel = NULL;
        sys_nh_info_ip_tunnel_t* p_nh_ip_tunnel_info = (sys_nh_info_ip_tunnel_t*)p_nh_info;

        p_ol_tunnel = _sys_usw_nh_lkup_tunnel(lchip, p_nh_ip_tunnel_info->dest_logic_port);
        if(p_nh_ip_tunnel_info->bind_ldp && p_ol_tunnel &&
            CTC_FLAG_ISSET(p_ol_tunnel->flag, SYS_NH_OL_TUNNEL_DIRTY))
        {
            return CTC_E_HW_BUSY;
        }
    }
    return CTC_E_NONE;
}




int32
sys_usw_nh_api_update(uint8 lchip, uint32 nhid, sys_nh_param_com_t* p_nh_com_para)
{
    p_sys_nh_update_cb_t nh_update_cb;
    sys_usw_nh_type_t nh_type;
    sys_nh_info_com_t* p_nh_info = NULL;
    int32 ret = CTC_E_NONE;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint8 alloc_offset = 0;

    nh_type = p_nh_com_para->hdr.nh_param_type;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info));
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_ext_by_nhid(lchip, nhid, &(p_nh_com_para->hdr.p_nh_info_ext), 0));

    if (nh_type != p_nh_info->hdr.nh_entry_type)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Nexthop type  mismatch \n");
        return CTC_E_INVALID_CONFIG;
    }

    if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV))
    {
        if(p_nh_com_para->hdr.change_type == SYS_NH_CHANGE_TYPE_FWD_TO_UNROV ||
            p_nh_com_para->hdr.change_type == SYS_NH_CHANGE_TYPE_UPDATE_FWD_ATTR)
        {
            return CTC_E_NONE;
        }

        if(p_nh_com_para->hdr.change_type == SYS_NH_CHANGE_TYPE_UNROV_TO_FWD)
        {
            CTC_ERROR_RETURN(_sys_usw_nh_alloc_offset_by_nhtype(lchip, p_nh_com_para, p_nh_info));
            alloc_offset = 1;
        }
    }
    else
    {
        if(p_nh_com_para->hdr.change_type == SYS_NH_CHANGE_TYPE_UNROV_TO_FWD)
        {
           p_nh_com_para->hdr.change_type = SYS_NH_CHANGE_TYPE_UPDATE_FWD_ATTR;
        }
    }

    p_nh_com_para->hdr.have_dsfwd  |= CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD);
    p_nh_com_para->hdr.have_dsfwd1  |= CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1);

    if ((SYS_NH_CHANGE_TYPE_UNROV_TO_FWD == p_nh_com_para->hdr.change_type)/*for ECMP*/
        && p_nh_com_para->hdr.p_nh_info_ext && p_nh_com_para->hdr.p_nh_info_ext->ecmp_list)
    {
        if (DRV_FROM_AT(lchip))
        {
            p_nh_com_para->hdr.have_dsfwd1 = 1;
        }
        else
        {
            p_nh_com_para->hdr.have_dsfwd = 1;
        }
    }
    p_nh_com_para->hdr.is_update = 1;
    nh_update_cb = p_nh_master->callbacks_nh_update[nh_type];
    if(nh_update_cb)
    {
       ret = (* nh_update_cb)(lchip, p_nh_info, p_nh_com_para);
    }

    SYS_USW_REGISTER_WB_SYNC_EN(SYS_PP_BASE(lchip), CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM, 1);

    if (ret && alloc_offset)
    {
        _sys_usw_nh_free_offset_by_nhinfo(lchip, nh_type, p_nh_info);
    }

    return ret;
}

int32
sys_usw_nh_api_get(uint8 lchip, uint32 nhid, void* p_nh_para)
{
    p_sys_nh_get_cb_t nh_get_cb;
    sys_usw_nh_type_t nh_type;
    sys_nh_info_com_t* p_nh_info;
    int32 ret = CTC_E_NONE;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info));

    nh_type = p_nh_info->hdr.nh_entry_type;
    nh_get_cb = p_nh_master->callbacks_nh_get[nh_type];
    if(nh_get_cb)
    {
       ret = (* nh_get_cb)(lchip, p_nh_info, p_nh_para);
    }
    else
    {
        return CTC_E_FEATURE_NOT_SUPPORT;
    }

    return ret;
}

int32
sys_usw_nh_update_ad(uint8 lchip, uint32 nhid, uint8 update_type, uint32 nhid_type, sys_nh_info_dsnh_t *p_dsnh)
{
    sys_nh_info_com_t* p_nh_info;
    int32 ret = CTC_E_NONE;

    sal_memset(p_dsnh, 0, sizeof(sys_nh_info_dsnh_t));
    if (update_type == 0xFF)
    {
       sys_nh_db_arp_t* p_arp = NULL;
       sys_nh_db_arp_nh_node_t* p_arp_nh_node = NULL;
       ctc_list_pointer_node_t* node = NULL;

        p_arp = (sys_usw_nh_lkup_arp_id(lchip, nhid));
        if (NULL == p_arp)
        {
            return CTC_E_NOT_EXIST;
        }

        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM, 1);
        CTC_LIST_POINTER_LOOP(node, p_arp->pd->nh_list)
        {
            p_arp_nh_node = _ctc_container_of(node, sys_nh_db_arp_nh_node_t, head);
            CTC_ERROR_RETURN(p_arp->pd->updateNhp(lchip, p_arp, p_arp_nh_node->nhid));
        }
        /* 1) One Arp only corresponds to one ipuc nexthop in general.
        2) Multiple ipuc nexthop use the same arp, only the fisrt ipuc nexthop exists mergedsfwd mode. */
        if (ctc_list_pointer_head(p_arp->pd->nh_list))
        {
            p_arp_nh_node = _ctc_container_of(ctc_list_pointer_head(p_arp->pd->nh_list), sys_nh_db_arp_nh_node_t, head);
            _sys_usw_nh_get_nhinfo(lchip, p_arp_nh_node->nhid, p_dsnh);
            p_dsnh->need_lock = 1;
        }
        return CTC_E_NONE;
    }
   CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info));
   if(nhid_type != p_nh_info->hdr.nh_entry_type)
   {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Nexthop type  mismatch \n");
       return CTC_E_INVALID_CONFIG;
   }

    if ((update_type == SYS_NH_CHANGE_TYPE_NH_DELETE)
        && (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED)) )
    {
        return CTC_E_IN_USE;
    }

   if (update_type != SYS_NH_CHANGE_TYPE_ADD_DYNTBL)
    {

        sys_nh_info_mpls_t* p_mpls_nh = NULL;
        sys_nh_info_ipuc_t* p_ipuc_nh = NULL;
        uint8 gchip_id = 0;

        _sys_usw_nh_get_nhinfo(lchip, nhid, p_dsnh);
		p_dsnh->need_lock =1;

        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
        {
            ret = sys_usw_nh_merge_dsfwd_disable(lchip, nhid, CTC_FEATURE_NEXTHOP);
            p_dsnh->merge_dsfwd = 2;
        }

        /*force to merge_dsfwd == 1, because the forwarding table maybe still use merge dsfwd*/
        if (update_type == SYS_NH_CHANGE_TYPE_NH_DELETE)
        {
            sys_usw_get_gchip_id(lchip, &gchip_id);
            p_dsnh->dest_map = SYS_ENCODE_DESTMAP(gchip_id, SYS_RSV_PORT_DROP_ID);
            p_dsnh->gport = CTC_MAP_LPORT_TO_GPORT(gchip_id, SYS_RSV_PORT_DROP_ID);
            p_dsnh->drop_pkt = 0xff;    /*indate delete*/
            p_dsnh->aps_en  = 0;
            p_dsnh->ecmp_valid = 0;
            p_dsnh->is_ecmp_intf = 0;
            p_dsnh->merge_dsfwd = 1;
        }

        /*update oam mep*/
        p_mpls_nh = (sys_nh_info_mpls_t*)p_nh_info;
        if (p_mpls_nh->hdr.nh_entry_type == SYS_NH_TYPE_MPLS)
        {
            _sys_usw_nh_update_oam_mep(lchip, p_mpls_nh->pd->oam_list, 0, p_dsnh);
        }
        else if (p_mpls_nh->hdr.nh_entry_type == SYS_NH_TYPE_IPUC)
        {
            p_ipuc_nh = (sys_nh_info_ipuc_t*)p_nh_info;
            /*update oam mep*/
            _sys_usw_nh_update_oam_mep(lchip, p_ipuc_nh->pd->oam_list, 0, p_dsnh);
        }
        else if (p_nh_info->hdr.nh_entry_type == SYS_NH_TYPE_SRV6)
        {
            sys_nh_info_srv6_t* p_srv6_nh = NULL;
            p_srv6_nh = (sys_nh_info_srv6_t*)p_nh_info;
            if (p_srv6_nh->ecmp_if_id != 0)
            {
                p_dsnh->merge_dsfwd = 1;
            }
        }

    }

    return ret;
}



#define _________offset__________

int32
_sys_usw_nh_get_dsnh_offset_by_nhid(uint8 lchip, uint32 nhid, uint32 *p_dsnh_offset, uint8* p_use_dsnh8w)
{
    sys_nh_info_com_t* p_nhinfo;
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo));
    *p_dsnh_offset = p_nhinfo->hdr.dsnh_offset;  /* modified */
    if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
    {
        *p_use_dsnh8w = TRUE;
    }
    return CTC_E_NONE;
}

int32
_sys_usw_nh_get_resolved_offset(uint8 lchip, sys_usw_nh_res_offset_type_t type, uint32* p_offset)
{
    sys_nh_offset_attr_t* p_res_offset;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    /*Always get chip 0's offset, all chip should be same,
    maybe we don't need to store this value per-chip*/
    p_res_offset = &(p_nh_master->sys_nh_resolved_offset[type]);
    *p_offset = p_res_offset->offset_base;
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Type = %d, resolved offset = 0x%x\n", type, *p_offset);

    return CTC_E_NONE;
}

/**
 @brief This function is used to alloc dynamic offset

 @return CTC_E_XXX
 */
int32
sys_usw_nh_offset_alloc(uint8 lchip, sys_nh_entry_table_type_t entry_type,
                              uint32 entry_num, uint32* p_offset)
{
    sys_usw_opf_t opf;
    uint32 entry_size;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];

    if (0 == entry_num)
    {
        return CTC_E_NONE;
    }
    *p_offset = 0;
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_index = p_nh_master->nh_table_info_array[entry_type].opf_pool_type + OPF_NH_DYN1_SRAM;
    entry_size = p_nh_master->nh_table_info_array[entry_type].entry_size;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.multiple = entry_size;
    entry_size = entry_size * entry_num;
    opf.reverse = (p_nh_master->nh_table_info_array[entry_type].alloc_dir == 1) ? 1 : 0;
    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, entry_size, p_offset));

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "lchip = %d, entry_type = %d, entry_number = %d, offset = 0x%x\n",
                   lchip, entry_type, entry_num, *p_offset);
    p_nh_master->nhtbl_used_cnt[entry_type] += entry_size;

    return CTC_E_NONE;
}

int32
sys_usw_nh_offset_alloc_with_multiple(uint8 lchip, sys_nh_entry_table_type_t entry_type,
                                            uint32 entry_num, uint16 multi, uint32* p_offset)
{
    sys_usw_opf_t opf;
    uint32 entry_size;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    entry_size = p_nh_master->nh_table_info_array[entry_type].entry_size;
    opf.pool_index = p_nh_master->nh_table_info_array[entry_type].opf_pool_type + OPF_NH_DYN1_SRAM;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.multiple = multi;
    opf.reverse = (p_nh_master->nh_table_info_array[entry_type].alloc_dir == 1) ? 1 : 0;
    entry_size = entry_size * entry_num;

    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, entry_size, p_offset));

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "lchip = %d, entry_type = %d, entry_number = %d, multi = %d, offset = 0x%x\n",
                   lchip, entry_type, entry_num, multi, *p_offset);
    p_nh_master->nhtbl_used_cnt[entry_type] += entry_size;
    return CTC_E_NONE;
}

int32
sys_usw_nh_offset_alloc_with_direction(uint8 lchip, sys_nh_entry_table_type_t entry_type,
                              uint32 entry_num, uint8 reverse, uint32* p_offset)
{
    sys_usw_opf_t opf;
    uint32 entry_size;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];

    *p_offset = 0;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_index = p_nh_master->nh_table_info_array[entry_type].opf_pool_type + OPF_NH_DYN1_SRAM;
    entry_size = p_nh_master->nh_table_info_array[entry_type].entry_size;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.multiple = entry_size;
    entry_size = entry_size * entry_num;
    opf.reverse = reverse;
    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, entry_size, p_offset));

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "lchip = %d, entry_type = %d, entry_number = %d, offset = 0x%x\n",
                   lchip, entry_type, entry_num, *p_offset);
    p_nh_master->nhtbl_used_cnt[entry_type] += entry_size;

    return CTC_E_NONE;
}

int32
sys_usw_nh_offset_alloc_from_position(uint8 lchip, sys_nh_entry_table_type_t entry_type,
                                            uint32 entry_num, uint32 start_offset)
{
    sys_usw_opf_t opf;
    uint32 entry_size;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_index = p_nh_master->nh_table_info_array[entry_type].opf_pool_type + OPF_NH_DYN1_SRAM;
    entry_size = p_nh_master->nh_table_info_array[entry_type].entry_size;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.multiple = entry_size;
    entry_size = entry_size * entry_num;
    opf.reverse = (p_nh_master->nh_table_info_array[entry_type].alloc_dir == 1) ? 1 : 0;

    CTC_ERROR_RETURN(sys_usw_opf_alloc_offset_from_position(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf,  entry_size, start_offset));

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "lchip = %d, entry_type = %d, entry_number = %d, offset = 0x%x\n",
                   lchip, entry_type, entry_num, start_offset);

    p_nh_master->nhtbl_used_cnt[entry_type] += entry_size;
    return CTC_E_NONE;
}


/**
 @brief This function is used to free dynamic offset

 */
int32
sys_usw_nh_offset_free(uint8 lchip, sys_nh_entry_table_type_t entry_type,
                             uint32 entry_num, uint32 offset)
{

    sys_usw_opf_t opf;
    uint32 entry_size;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];

    if (((offset == 0) && (SYS_NH_ENTRY_TYPE_LOGIC_REP != entry_type)) || (CTC_MAX_UINT32_VALUE == offset))
    {/*offset 0 is reserved*/
        return CTC_E_NONE;
    }
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "lchip = %d, entry_type = %d, entry_number = %d, offset = %d\n",
                   lchip, entry_type, entry_num, offset);
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_index = p_nh_master->nh_table_info_array[entry_type].opf_pool_type + OPF_NH_DYN1_SRAM;
    entry_size = p_nh_master->nh_table_info_array[entry_type].entry_size;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    entry_size = entry_size * entry_num;
    CTC_ERROR_RETURN(sys_usw_opf_free_offset(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, entry_size, offset));

    if(p_nh_master->nhtbl_used_cnt[entry_type] >= entry_size)
    {
       p_nh_master->nhtbl_used_cnt[entry_type] -= entry_size;
    }
    return CTC_E_NONE;

}

int32
sys_usw_nh_swap_nexthop_offset(uint8 lchip, uint32 nhid, uint32 nhid2)
{
    uint32 dsnh_offset = 0;
    uint32 dsnh_offset2 = 0;
    DsNextHop4W_m dsnh;
    DsNextHop4W_m dsnh2;
    uint32 cmd = 0;
    sys_nh_info_com_t*p_nhinfo = NULL;
    sys_nh_info_com_t*p_nhinfo2 = NULL;

    if (nhid == nhid2)
    {
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo));
    if (NULL == p_nhinfo)
    {
        return CTC_E_NH_INVALID_NHID;
    }

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid2, &p_nhinfo2));
    if (NULL == p_nhinfo2)
    {
        return CTC_E_NH_INVALID_NHID;
    }

    dsnh_offset = p_nhinfo->hdr.dsnh_offset;
    dsnh_offset2 = p_nhinfo2->hdr.dsnh_offset;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Swap nhid%d, offset:%d, nhid2:%d, offset2:%d \n", nhid, dsnh_offset, nhid2, dsnh_offset2);

    cmd = DRV_IOR(DsNextHop4W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dsnh_offset, cmd, &dsnh));
    cmd = DRV_IOR(DsNextHop4W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dsnh_offset2, cmd, &dsnh2));

    cmd = DRV_IOW(DsNextHop4W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dsnh_offset, cmd, &dsnh2));
    cmd = DRV_IOW(DsFwd_t, DsFwd_nextHopPtr_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_nhinfo->hdr.dsfwd_offset, cmd, &dsnh_offset2));
    if (DRV_FROM_AT(lchip) && p_nhinfo->hdr.dsfwd1_offset)
    {
        cmd = DRV_IOW(DsFwd1_t, DsFwd_nextHopPtr_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_nhinfo->hdr.dsfwd1_offset, cmd, &dsnh_offset2));
    }
    p_nhinfo->hdr.dsnh_offset = dsnh_offset2;

    cmd = DRV_IOW(DsNextHop4W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, dsnh_offset2, cmd, &dsnh));
    cmd = DRV_IOW(DsFwd_t, DsFwd_nextHopPtr_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_nhinfo2->hdr.dsfwd_offset, cmd, &dsnh_offset));
    if (DRV_FROM_AT(lchip) && p_nhinfo2->hdr.dsfwd1_offset)
    {
        cmd = DRV_IOW(DsFwd1_t, DsFwd_nextHopPtr_f);
        CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, p_nhinfo2->hdr.dsfwd1_offset, cmd, &dsnh_offset));
    }
    p_nhinfo2->hdr.dsnh_offset = dsnh_offset;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_alloc_logic_replicate_offset(uint8 lchip, sys_nh_info_com_t* p_nhinfo, uint32 dest_gport, uint32 group_id)
{
#if 0

    ctc_slistnode_t* ctc_slistnode = NULL;
    sys_nh_repli_offset_node_t *p_offset_node = NULL;
    bool found = FALSE;
    int32 ret = 0;
    uint8 type = 0;
    uint8 multi = 0;
    uint32 offset = 0;
    sys_usw_nh_master_t* p_usw_nh_master = g_usw_nh_master[lchip];

    if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
    {
        type = SYS_NH_ENTRY_TYPE_NEXTHOP_8W;
        multi = 2;
    }
    else
    {
        type = SYS_NH_ENTRY_TYPE_NEXTHOP_4W;
        multi = 1;
    }


    CTC_SLIST_LOOP(p_usw_nh_master->repli_offset_list, ctc_slistnode)
    {
        p_offset_node = _ctc_container_of(ctc_slistnode, sys_nh_repli_offset_node_t, head);
        if (p_offset_node->bitmap != 0xFFFFFFFF &&
            p_offset_node->dest_gport == dest_gport &&
            p_offset_node->group_id == group_id)
        {
            found = TRUE;
            break;
        }
    }

    if (TRUE == found)
    {
        uint8 bit = 0;

        for (bit = 0; bit < 32; bit++)
        {
            if (!CTC_IS_BIT_SET(p_offset_node->bitmap, bit))
            {
                CTC_BIT_SET(p_offset_node->bitmap , bit);
                offset = bit*multi;
                p_nhinfo->hdr.dsnh_offset = p_offset_node->start_offset + offset;
                //p_nhinfo->hdr.p_data = (void*)p_offset_node;

                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Update alloc_logic_replicate_offset :%d, gport:0x%x, group-id:%d\n",
                               p_nhinfo->hdr.dsnh_offset, dest_gport, group_id);

                return CTC_E_NONE;
            }
        }
    }

    p_offset_node =  mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_repli_offset_node_t));
    if (NULL == p_offset_node)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_offset_node, 0, sizeof(sys_nh_repli_offset_node_t));

    offset = SYS_NH_MCAST_LOGIC_MAX_CNT*multi;
    ret = sys_usw_nh_offset_alloc_with_multiple(lchip, type,
                                                      SYS_NH_MCAST_LOGIC_MAX_CNT,
                                                      offset,
                                                      &p_offset_node->start_offset);
    if (ret < 0)
    {
        mem_free(p_offset_node);
        return ret;
    }

    CTC_BIT_SET(p_offset_node->bitmap , 0);
    p_offset_node->dest_gport = dest_gport;
    p_offset_node->group_id = group_id;

    p_nhinfo->hdr.dsnh_offset = p_offset_node->start_offset;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "New alloc_logic_replicate_offset :%d, gport:0x%x, group-id:%d\n",
                   p_nhinfo->hdr.dsnh_offset, dest_gport, group_id);

	ctc_slist_add_tail(p_usw_nh_master->repli_offset_list, &(p_offset_node->head));

    //p_nhinfo->hdr.p_data = (void*)p_offset_node;
#endif

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_nh_free_logic_replicate_offset(uint8 lchip, sys_nh_info_com_t* p_nhinfo)
{
/*For D2 xgpon*/
#if 0
    sys_nh_repli_offset_node_t *p_offset_node = NULL;
    uint8 type = 0;
    uint8 multi = 0;
    uint8 bit = 0;
    sys_usw_nh_master_t* p_usw_nh_master = g_usw_nh_master[lchip];

    if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
    {
        type = SYS_NH_ENTRY_TYPE_NEXTHOP_8W;
        multi = 2;
    }
    else
    {
        type = SYS_NH_ENTRY_TYPE_NEXTHOP_4W;
        multi = 1;
    }


    //p_offset_node = (sys_nh_repli_offset_node_t *)p_nhinfo->hdr.p_data;

    if (NULL == p_offset_node)
    {
        return CTC_E_NOT_EXIST;
    }

    bit =  (p_nhinfo->hdr.dsnh_offset - p_offset_node->start_offset) / multi;

    CTC_BIT_UNSET(p_offset_node->bitmap , bit);


    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "free_logic_replicate_offset :%d, gport:0x%x\n", p_nhinfo->hdr.dsnh_offset, p_offset_node->dest_gport);

    if (p_offset_node->bitmap == 0)
    {

        ctc_slist_delete_node(p_usw_nh_master->repli_offset_list, &(p_offset_node->head));

        CTC_ERROR_RETURN(sys_usw_nh_offset_free(lchip, type,
                                                      SYS_NH_MCAST_LOGIC_MAX_CNT,
                                                      p_offset_node->start_offset));
        mem_free(p_offset_node);
        //p_nhinfo->hdr.p_data = NULL;
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "free_offset node!!!!!\n");
    }
#endif
    return CTC_E_NONE;
}

int32
_sys_usw_nh_alloc_offset_by_nhtype(uint8 lchip, sys_nh_param_com_t* p_nh_com_para, sys_nh_info_com_t* p_nhinfo)
{
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];
    uint32 dsnh_offset = 0;
    uint8 use_rsv_dsnh = 0;
     /*uint8 remote_chip = 0;*/
    uint8 dsnh_entry_num = 0;
    uint8 tunnel_is_spme = 0;
    uint8 pkt_nh_edit_mode  = SYS_NH_IGS_CHIP_EDIT_MODE;
    uint8 dest_gchip = 0;
    uint8 dest_gchip1 = 0;
    uint8 use_dsnh8w = 0;
    uint32 dest_gport = 0;
    uint32 dest_gport1 = 0xFFFFFFFF;
    uint8 xgpon_en = 0;
    int32 ret = 0;
    uint32 old_entry_flag = 0;

    sys_usw_get_gchip_id(lchip, &dest_gchip);
    dest_gchip1 = dest_gchip;
    old_entry_flag = p_nhinfo->hdr.nh_entry_flags;
    switch (p_nh_com_para->hdr.nh_param_type)
    {
    case SYS_NH_TYPE_BRGUC:
        {
            sys_nh_param_brguc_t* p_nh_param = (sys_nh_param_brguc_t*)p_nh_com_para;
            sys_nh_info_brguc_t* p_brg_nhinfo = (sys_nh_info_brguc_t*)p_nhinfo;
            dsnh_offset = p_nh_param->dsnh_offset;
            p_brg_nhinfo->nh_sub_type = p_nh_param->nh_sub_type;
            if (p_nh_param->nh_sub_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_VLAN_EDIT)
            {
                if (CTC_FLAG_ISSET(p_nh_param->p_vlan_edit_info->flag, CTC_VLAN_NH_MTU_CHECK_EN))
                {
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Mtu check is not supported \n");
                    return CTC_E_NOT_SUPPORT;
                }

                if ((0 == p_nh_param->p_vlan_edit_info->flag)
                    &&(0 == p_nh_param->p_vlan_edit_info->edit_flag)
                    &&(0 == p_nh_param->p_vlan_edit_info->loop_nhid)
                    && (p_nh_param->p_vlan_edit_info->svlan_edit_type == CTC_VLAN_EGRESS_EDIT_NONE
                        && p_nh_param->p_vlan_edit_info->cvlan_edit_type == CTC_VLAN_EGRESS_EDIT_NONE)
                    && (!p_nh_param->p_vlan_edit_nh_param->logic_port)
                    && (!p_nh_param->p_vlan_edit_nh_param->logic_port_check)
                    && (0 == p_nh_param->p_vlan_edit_nh_param->cid)
                    && (0 == p_nh_param->p_vlan_edit_info->user_vlanptr))
                {
                    CTC_ERROR_RETURN(_sys_usw_nh_get_resolved_offset(lchip,
                                         SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH, &dsnh_offset));
                    p_nhinfo->hdr.dsnh_entry_num  = 1;
                    use_rsv_dsnh = 1;
                }
                else
                {
                    p_nhinfo->hdr.dsnh_entry_num  = 1;
                    use_dsnh8w = p_nh_param->p_vlan_edit_nh_param
                        && (p_nh_param->p_vlan_edit_nh_param->logic_port ||p_nh_param->p_vlan_edit_nh_param->logic_port_check)
                        && (p_nh_param->p_vlan_edit_info->cvlan_edit_type != CTC_VLAN_EGRESS_EDIT_NONE)
                        && (p_nh_param->p_vlan_edit_info->cvlan_edit_type != CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE);

                    if (use_dsnh8w ||
                        p_nh_param->p_vlan_edit_info->cvlan_edit_type == CTC_VLAN_EGRESS_EDIT_STRIP_VLAN
                        || (p_nh_param->p_vlan_edit_info->loop_nhid
                        && (p_nh_param->p_vlan_edit_info->cvlan_edit_type != CTC_VLAN_EGRESS_EDIT_NONE ||
                            CTC_FLAG_ISSET(p_nh_param->p_vlan_edit_info->edit_flag, CTC_VLAN_EGRESS_EDIT_SVLAN_AWARE)))
                        || (p_nh_param->p_vlan_edit_nh_param && p_nh_param->p_vlan_edit_nh_param->cid && !g_usw_nh_master[lchip]->cid_use_4w)
                        || (CTC_FLAG_ISSET(p_nh_param->p_vlan_edit_info->flag, CTC_VLAN_NH_STATS_EN) && g_usw_nh_master[lchip]->cid_use_4w))
                    {
                        CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
                    }

                    sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
                    if (xgpon_en && DRV_IS_DUET2(lchip))
                    {
                        if (CTC_FLAG_ISSET(p_nh_param->p_vlan_edit_info->flag, CTC_VLAN_NH_SERVICE_QUEUE_FLAG))
                        {
                            dest_gport = p_nh_param->gport;
                            //CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_REPLI_EN);
                            CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HORIZON_SPLIT_EN);
                        }

                        if (CTC_FLAG_ISSET(p_nh_param->p_vlan_edit_info->flag, CTC_VLAN_NH_LENGTH_ADJUST_EN))
                        {
                            p_nh_param->p_vlan_edit_info->stats_id = 0;
                            use_rsv_dsnh = 1;
                            dsnh_offset = p_master->xlate_nh_offset + p_nh_param->p_vlan_edit_info->output_svid;
                        }
                    }
                    else if(p_nh_param->p_vlan_edit_nh_param && sys_usw_nh_is_xgpon_hybrid(lchip, p_nh_param->p_vlan_edit_nh_param->logic_port))
                    {
                       CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
                    }
                }
                pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
                dest_gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_param->gport);
                dest_gport1 = p_nh_param->gport;
            }
            else if (p_nh_param->nh_sub_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BASIC)
            {
                CTC_ERROR_RETURN(_sys_usw_nh_get_resolved_offset(lchip,
                                     SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH, &dsnh_offset));
                p_nhinfo->hdr.dsnh_entry_num  = 1;
                use_rsv_dsnh = 1;
            }
            else if (p_nh_param->nh_sub_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BYPASS)
            {
                CTC_ERROR_RETURN(_sys_usw_nh_get_resolved_offset(lchip,
                                     SYS_NH_RES_OFFSET_TYPE_BYPASS_NH, &dsnh_offset));

                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE);

                p_nhinfo->hdr.dsnh_entry_num  = 1;
                use_rsv_dsnh = 1;
            }
        }
        break;

    case SYS_NH_TYPE_IPUC:
        {
            sys_nh_param_ipuc_t* p_nh_param = (sys_nh_param_ipuc_t*)p_nh_com_para;
            ctc_ip_nh_param_t* p_ctc_nh_param = (ctc_ip_nh_param_t*)p_nh_param->p_ipuc_param;

            if (p_ctc_nh_param->logic_port || (p_ctc_nh_param->stats_id && g_usw_nh_master[lchip]->cid_use_4w))
            {
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
            }

            dsnh_offset = p_ctc_nh_param->dsnh_offset;
            {
                p_nhinfo->hdr.dsnh_entry_num  = 1;
                dest_gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_ctc_nh_param->oif.gport);
            }
            if (CTC_FLAG_ISSET(p_ctc_nh_param->flag, CTC_IP_NH_FLAG_UNROV))
            {
                p_nhinfo->hdr.dsnh_entry_num = 0;
            }

            if (p_master->pkt_nh_edit_mode == SYS_NH_EDIT_MODE_USER_DEF)
            {
                pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
            }
            dest_gport1 = p_ctc_nh_param->oif.gport;
        }
        break;

    case SYS_NH_TYPE_IP_TUNNEL:
        {
            sys_nh_param_ip_tunnel_t* p_nh_param = (sys_nh_param_ip_tunnel_t*)p_nh_com_para;
            if (CTC_FLAG_ISSET(p_nh_param->p_ip_nh_param->tunnel_info.flag,CTC_IP_NH_TUNNEL_FLAG_OVERLAY_CROSS_VNI)
                ||  (SYS_NH_IP_TUNNEL_IS_OVERLAY_TUNNEL(p_nh_param->p_ip_nh_param) && g_usw_nh_master[lchip]->bpe_mc_en)
                || (p_nh_param->p_ip_nh_param->tunnel_info.logic_port)
                ||(p_nh_param->p_ip_nh_param->tunnel_info.inner_packet_type ==PKT_TYPE_IPV4 )
                ||(p_nh_param->p_ip_nh_param->tunnel_info.inner_packet_type ==PKT_TYPE_IPV6 )
                ||CTC_FLAG_ISSET(p_nh_param->p_ip_nh_param->tunnel_info.flag,CTC_IP_NH_TUNNEL_FLAG_XERSPN_WITH_EXT_HDR)
                ||(0 != p_nh_param->p_ip_nh_param->tunnel_info.vn_id)
                ||CTC_FLAG_ISSET(p_nh_param->p_ip_nh_param->tunnel_info.flag,CTC_IP_NH_TUNNEL_FLAG_LOGIC_PORT_CHECK)
                || p_nh_param->p_ip_nh_param->tunnel_info.udf_profile_id
                || CTC_FLAG_ISSET(p_nh_param->p_ip_nh_param->tunnel_info.flag, CTC_IP_NH_TUNNEL_FLAG_STRIP_CVLAN)
                || CTC_FLAG_ISSET(p_nh_param->p_ip_nh_param->tunnel_info.flag, CTC_IP_NH_TUNNEL_FLAG_SVLAN_TPID_VALID))
            {
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
            }

            dsnh_offset = p_nh_param->p_ip_nh_param->dsnh_offset;
            p_nhinfo->hdr.dsnh_entry_num  = 1;
            pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
            if (DRV_FROM_TMM(lchip)
                && (CTC_TUNNEL_TYPE_IPV4_NAT == p_nh_param->p_ip_nh_param->tunnel_info.tunnel_type
                    || CTC_TUNNEL_TYPE_IPV6_NAT == p_nh_param->p_ip_nh_param->tunnel_info.tunnel_type))
            {
                pkt_nh_edit_mode  = SYS_NH_IGS_CHIP_EDIT_MODE;
            }
            if (!CTC_FLAG_ISSET(p_nh_param->p_ip_nh_param->tunnel_info.flag, CTC_IP_NH_TUNNEL_FLAG_REROUTE_WITH_TUNNEL_HDR))
            {
                dest_gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_param->p_ip_nh_param->oif.gport);
                dest_gport1 = p_nh_param->p_ip_nh_param->oif.gport;
            }

            if (CTC_FLAG_ISSET(p_nh_param->p_ip_nh_param->flag, CTC_IP_NH_FLAG_UNROV))
            {
                p_nhinfo->hdr.dsnh_entry_num = 0;
            }
        }
        break;

    case SYS_NH_TYPE_WLAN_TUNNEL:
        {
            sys_nh_param_wlan_tunnel_t* p_nh_param = (sys_nh_param_wlan_tunnel_t*)p_nh_com_para;
            CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
            dsnh_offset = p_nh_param->p_wlan_nh_param->dsnh_offset;
            p_nhinfo->hdr.dsnh_entry_num  = 1;
            pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
        }
        break;

    case SYS_NH_TYPE_SRV6:
        {
            sys_nh_param_srv6_t* p_nh_param = (sys_nh_param_srv6_t*)p_nh_com_para;
            uint8 srv6_encap = 0;
            if ((p_nh_param->p_srv6_nh_param->logic_port)
                ||CTC_FLAG_ISSET(p_nh_param->p_srv6_nh_param->flag,CTC_NH_SRV6_FLAG_LOGIC_PORT_CHECK)
                || (p_nh_param->p_srv6_nh_param->vlan_info != NULL))
            {
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
            }

            if ((CTC_NH_SRV6_TYPE_E_ENCAPS == p_nh_param->p_srv6_nh_param->srv6_type)
                || (CTC_NH_SRV6_TYPE_H_ENCAPS == p_nh_param->p_srv6_nh_param->srv6_type)
                || (CTC_NH_SRV6_TYPE_H_ENCAPS_L2 == p_nh_param->p_srv6_nh_param->srv6_type))
            {
                srv6_encap = 1;
            }
            if (srv6_encap && g_usw_nh_master[lchip]->cid_use_4w &&
                p_nh_param->p_srv6_nh_param->stats_id && (p_nh_param->p_srv6_nh_param->flow_label_mode != CTC_NH_FLOW_LABEL_NONE))
            {
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
            }

            dsnh_offset = p_nh_param->p_srv6_nh_param->dsnh_offset;
            p_nhinfo->hdr.dsnh_entry_num  = 1;
            pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
            if (CTC_FLAG_ISSET(p_nh_param->p_srv6_nh_param->flag,CTC_NH_SRV6_FLAG_UNROV))
            {
                p_nhinfo->hdr.dsnh_entry_num = 0;
            }
        }
        break;
    case SYS_NH_TYPE_OVERLAY_VNI:
        {
            sys_nh_param_ol_vni_t* p_nh_param = (sys_nh_param_ol_vni_t*)p_nh_com_para;
            if ((CTC_FLAG_ISSET(p_nh_param->p_ol_vni_param->flag, CTC_NH_OL_VNI_FLAG_FID))
                || CTC_FLAG_ISSET(p_nh_param->p_ol_vni_param->flag, CTC_NH_OL_VNI_FLAG_STRIP_CVLAN)
                || CTC_FLAG_ISSET(p_nh_param->p_ol_vni_param->flag, CTC_NH_OL_VNI_FLAG_CROSS_VNI)
                || (CTC_FLAG_ISSET(p_nh_param->p_ol_vni_param->flag, CTC_NH_OL_VNI_FLAG_VLAN_EDIT)
                     && ((p_nh_param->p_ol_vni_param->vlan_info.cvlan_edit_type != CTC_VLAN_EGRESS_EDIT_NONE
                           && p_nh_param->p_ol_vni_param->vlan_info.cvlan_edit_type != CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE)))
                || (CTC_FLAG_ISSET(p_nh_param->p_ol_vni_param->vlan_info.flag, CTC_VLAN_NH_STATS_EN) && g_usw_nh_master[lchip]->cid_use_4w))
            {
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
            }
            dsnh_offset = p_nh_param->p_ol_vni_param->dsnh_offset;
            p_nhinfo->hdr.dsnh_entry_num  = 1;
            pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
        }
        break;
    case SYS_NH_TYPE_TRILL:
        {
            sys_nh_param_trill_t* p_nh_param = (sys_nh_param_trill_t*)p_nh_com_para;
            dsnh_offset = p_nh_param->p_trill_nh_param->dsnh_offset;
            p_nhinfo->hdr.dsnh_entry_num  = 1;
            pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
            dest_gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_param->p_trill_nh_param->oif.gport);
            dest_gport1 = p_nh_param->p_trill_nh_param->oif.gport;

            if (CTC_FLAG_ISSET(p_nh_param->p_trill_nh_param->flag, CTC_NH_TRILL_IS_UNRSV))
            {
                p_nhinfo->hdr.dsnh_entry_num = 0;
            }
        }
        break;

    case SYS_NH_TYPE_MISC:
        {
            sys_nh_param_misc_t* p_nh_param = (sys_nh_param_misc_t*)p_nh_com_para;
            uint16 span_id = 0;
            ctc_misc_nh_fp_edit_param_t* p_fp_edit = NULL;

            if(CTC_MISC_NH_TYPE_TO_CPU == p_nh_param->p_misc_param->type)
            {
                p_nhinfo->hdr.dsnh_entry_num  = 0;
            }
            else if ( CTC_MISC_NH_TYPE_LEAF_SPINE == p_nh_param->p_misc_param->type)
            {
                p_nhinfo->hdr.dsnh_entry_num  = 0;
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE);
            }
            else
            {
                dsnh_offset = p_nh_param->p_misc_param->dsnh_offset;
                p_nhinfo->hdr.dsnh_entry_num  = 1;

                if (CTC_MISC_NH_TYPE_FP_EDIT == p_nh_param->p_misc_param->type)
                {
                    p_fp_edit = (ctc_misc_nh_fp_edit_param_t *)&p_nh_param->p_misc_param->misc_param.over_l2edit;
                    span_id = p_fp_edit->span_id;
                }
                else if( CTC_MISC_NH_TYPE_ERSPAN == p_nh_param->p_misc_param->type )
                {
                    span_id = p_nh_param->p_misc_param->misc_param.erspan_edit.session_id;
                }

                if ((CTC_MISC_NH_TYPE_OVER_L2_WITH_TS == p_nh_param->p_misc_param->type) ||
                    (CTC_MISC_NH_TYPE_OVER_L2 == p_nh_param->p_misc_param->type) ||
                    (p_nh_param->p_misc_param->cid && !g_usw_nh_master[lchip]->cid_use_4w) ||
                    (p_nh_param->p_misc_param->stats_id && g_usw_nh_master[lchip]->cid_use_4w) ||
                    p_nh_param->p_misc_param->logic_port || span_id)
                {
                    CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
                }
                else if(CTC_MISC_NH_TYPE_FP_EDIT == p_nh_param->p_misc_param->type &&
                    p_fp_edit->span_id)
                {
                    CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
                }

                 pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;
                 dest_gchip = SYS_MAP_CTC_GPORT_TO_GCHIP(p_nh_param->p_misc_param->gport);
                 dest_gport1 = p_nh_param->p_misc_param->gport;
            }
        }
        break;

    case SYS_NH_TYPE_RSPAN:
        {
            sys_nh_param_rspan_t* p_nh_para = (sys_nh_param_rspan_t*)p_nh_com_para;
            dsnh_offset = p_nh_para->p_rspan_param->dsnh_offset;
            p_nhinfo->hdr.dsnh_entry_num  = 1;
             /*remote_chip = p_nh_para->p_rspan_param->remote_chip;*/
            pkt_nh_edit_mode  = SYS_NH_IGS_CHIP_EDIT_MODE;
        }
        break;

    case SYS_NH_TYPE_MPLS:
        {
            sys_nh_param_mpls_t* p_nh_para = (sys_nh_param_mpls_t*)p_nh_com_para;

            ctc_vlan_egress_edit_info_t* p_vlan_info = &p_nh_para->p_mpls_nh_param->nh_para.nh_param_push.nh_com.vlan_info;

            dsnh_offset = p_nh_para->p_mpls_nh_param->dsnh_offset;
            if ((p_nh_para->p_mpls_nh_param->nh_prop == CTC_MPLS_NH_PUSH_TYPE) &&
                ((p_nh_para->p_mpls_nh_param->nh_para.nh_param_push.nh_com.opcode == CTC_MPLS_NH_PUSH_OP_L2VPN)
                || (p_nh_para->p_mpls_nh_param->nh_para.nh_param_push.nh_com.opcode == CTC_MPLS_NH_PUSH_OP_ROUTE)))
            {
                if (!p_nh_para->p_mpls_nh_param->nh_para.nh_param_push.loop_nhid)
                {
                    CTC_ERROR_RETURN(sys_usw_nh_check_mpls_tunnel_is_spme(lchip, p_nh_para->p_mpls_nh_param->nh_para.nh_param_push.tunnel_id, &tunnel_is_spme));
                }
                if(((p_vlan_info != NULL)
                    && ((CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUTPUT_SVLAN_TPID_VALID))
                     ||((CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID))
                     ||(CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID))
                     || (p_vlan_info->cvlan_edit_type == CTC_VLAN_EGRESS_EDIT_STRIP_VLAN)))
                     && (!tunnel_is_spme))
                     || (p_nh_para->p_mpls_nh_param->logic_port))
                {
                    CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
                }
            }

            if (p_nh_para->p_mpls_nh_param->aps_en)
            {
                bool share_nh = FALSE;
                CTC_ERROR_RETURN(sys_usw_aps_get_share_nh(lchip, p_nh_para->p_mpls_nh_param->aps_bridge_group_id, &share_nh));
                p_nhinfo->hdr.dsnh_entry_num  = share_nh?1:2;
                p_nhinfo->hdr.nh_entry_flags  |= share_nh?SYS_NH_INFO_FLAG_IS_APS_SHARE_DSNH:0;
            }
            else
            {
                p_nhinfo->hdr.dsnh_entry_num  = 1;
            }
            pkt_nh_edit_mode  = SYS_NH_EGS_CHIP_EDIT_MODE;

            if (CTC_FLAG_ISSET(p_nh_para->p_mpls_nh_param->flag, CTC_MPLS_NH_IS_UNRSV))
            {
                p_nhinfo->hdr.dsnh_entry_num = 0;
            }
        }
        break;

    case SYS_NH_TYPE_ECMP:
    case SYS_NH_TYPE_MCAST:
    case SYS_NH_TYPE_DROP:
    case SYS_NH_TYPE_TOCPU:
    case SYS_NH_TYPE_UNROV:
    case SYS_NH_TYPE_ILOOP:
    case SYS_NH_TYPE_OVERLAY:
	case SYS_NH_TYPE_APS:
        p_nhinfo->hdr.dsnh_entry_num  = 0;
        break;

    default:
        return CTC_E_INVALID_PARAM;
    }

    /*No need alloc  and use dsnh offset*/
    if (0 == p_nhinfo->hdr.dsnh_entry_num)
    {
        return CTC_E_NONE;
    }

    if (use_rsv_dsnh)
    {
        CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_RSV_DSNH);
    }
    else if(CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_REPLI_EN))
    {
        CTC_ERROR_GOTO(_sys_usw_nh_alloc_logic_replicate_offset(lchip, p_nhinfo, dest_gport, dsnh_offset), ret, error_proc);
        CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH);
    }
    else if ((p_master->pkt_nh_edit_mode == SYS_NH_EDIT_MODE_USER_DEF && (pkt_nh_edit_mode == SYS_NH_EGS_CHIP_EDIT_MODE) && dsnh_offset) ||
           (p_master->pkt_nh_edit_mode == SYS_NH_EDIT_MODE_MISC && (pkt_nh_edit_mode == SYS_NH_EGS_CHIP_EDIT_MODE)))
    {
        if (CTC_IS_BIT_SET(dsnh_offset, SYS_USW_NH_DSNH_OFFSET_MAPPER) && DRV_FROM_AT(lchip))/*AT*/
        {
            uint32 dsnh_ptr = dsnh_offset&0x00FFFFFF;
            if ((0 == g_usw_nh_master[lchip]->nh_mapper_num)
                || (dsnh_ptr >= (g_usw_nh_master[lchip]->nh_mapper_num*SYS_NH_MAP_UNIT_SIZE))
                || (dsnh_ptr >= 0x40000))/*256K*/
            {
                ret = CTC_E_INVALID_CONFIG;
                goto error_proc;
            }
            dsnh_offset = 0;
            if (dest_gport1 != 0xFFFFFFFF)
            {
                SYS_MAP_CTC_GPORT_TO_GCHIP1(dest_gport1, dest_gchip1);
            }
            if (!SYS_GCHIP_IS_REMOTE(lchip, dest_gchip1) || (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV)))
            {
                CTC_ERROR_GOTO(sys_usw_nh_offset_alloc_with_direction(lchip, CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W) ?
                SYS_NH_ENTRY_TYPE_NEXTHOP_8W : SYS_NH_ENTRY_TYPE_NEXTHOP_4W, p_nhinfo->hdr.dsnh_entry_num, 1, &dsnh_offset), ret, error_proc);
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH);
            }
            p_nhinfo->hdr.dsnh_ptr = dsnh_ptr + g_usw_nh_master[lchip]->nh_mapper_base;
            CTC_ERROR_RETURN(_sys_usw_nh_set_nh_map(lchip, dsnh_ptr, dsnh_offset));
        }
        else
        {
            if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
            {
                if (dsnh_offset & 0x01)
                {
                    ret = CTC_E_INVALID_PARAM;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "DsNexthop offset (%u)is error\n", dsnh_offset);
                    goto error_proc;
                }
                dsnh_entry_num = p_nhinfo->hdr.dsnh_entry_num *2;
            }
            else
            {
                dsnh_entry_num = p_nhinfo->hdr.dsnh_entry_num ;
            }
            if (!CTC_IS_BIT_SET(dsnh_offset, SYS_USW_NH_DSNH_OFFSET_IGS_EDIT_BIT))
            {
                CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE);
                if (CTC_IS_BIT_SET(dsnh_offset, SYS_USW_NH_DSNH_OFFSET_NO_HW_BIT))
                {
                    CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW);
                }
            }
            dsnh_offset = SYS_USW_NH_DSNH_OFFSET_VALID(dsnh_offset);
            if(!SYS_GCHIP_IS_REMOTE(lchip, dest_gchip) &&
            ((!CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV)) ||
                (p_nh_com_para->hdr.change_type == SYS_NH_CHANGE_TYPE_UNROV_TO_FWD))
                && (!CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW)))
            {
                CTC_ERROR_GOTO(sys_usw_nh_check_max_glb_nh_offset(lchip, dsnh_offset), ret, error_proc);
                if (p_nh_com_para->hdr.nh_param_type != SYS_NH_TYPE_IP_TUNNEL)
                {
                    CTC_ERROR_GOTO(sys_usw_nh_check_glb_nh_offset(lchip, dsnh_offset, dsnh_entry_num, TRUE), ret, error_proc);
                }
                CTC_ERROR_GOTO(sys_usw_nh_set_glb_nh_offset(lchip, dsnh_offset, dsnh_entry_num, TRUE), ret, error_proc);
            }
        }
    }
    else
    {
        uint8 entry_type = CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W)?
                           SYS_NH_ENTRY_TYPE_NEXTHOP_8W : SYS_NH_ENTRY_TYPE_NEXTHOP_4W;
        if (p_nh_com_para->hdr.nh_param_type == SYS_NH_TYPE_RSPAN)
        {
            /*Only used for compatible GG Ingress Edit Mode */
            dsnh_offset = SYS_DSNH_INDEX_FOR_REMOTE_MIRROR;
        }

        CTC_ERROR_GOTO(sys_usw_nh_offset_alloc(lchip, entry_type, p_nhinfo->hdr.dsnh_entry_num, &dsnh_offset), ret, error_proc);
        if (DRV_FROM_AT(lchip))/*for stacking and none ingress edit mode, ingress nh offset must < nh_mapper_base */
        {
            if (g_usw_nh_master[lchip]->nh_mapper_base && (dsnh_offset >= g_usw_nh_master[lchip]->nh_mapper_base))
            {
                sys_usw_nh_offset_free(lchip, entry_type, p_nhinfo->hdr.dsnh_entry_num, dsnh_offset);
                ret = CTC_E_NO_RESOURCE;
                goto error_proc;
            }
        }

        CTC_SET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH);
    }
    p_nhinfo->hdr.dsnh_offset = dsnh_offset;
    return CTC_E_NONE;
error_proc:
    p_nhinfo->hdr.dsnh_entry_num = 0;
    p_nhinfo->hdr.nh_entry_flags = old_entry_flag;
    return ret;
}

int32
_sys_usw_nh_free_offset_by_nhinfo(uint8 lchip, sys_usw_nh_type_t nh_type, sys_nh_info_com_t* p_nhinfo)
{
    uint8 dsnh_entry_num = 0;

    if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_RSV_DSNH) || !p_nhinfo->hdr.dsnh_entry_num)
    {
        return CTC_E_NONE;
    }

    if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_REPLI_EN))
    {
        CTC_ERROR_RETURN(_sys_usw_nh_free_logic_replicate_offset(lchip, p_nhinfo));
        CTC_UNSET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH);
    }
    else if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH))
    {
        if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
        {
            CTC_ERROR_RETURN(sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, p_nhinfo->hdr.dsnh_entry_num, p_nhinfo->hdr.dsnh_offset));
        }
        else
        {
            CTC_ERROR_RETURN(sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, p_nhinfo->hdr.dsnh_entry_num, p_nhinfo->hdr.dsnh_offset));
        }


        CTC_UNSET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH);
        p_nhinfo->hdr.dsnh_offset = 0;

    }
    else if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE))
    {
        ds0_t ds;
        uint8 table_type = 0;
        uint8 free_hw = 1;
        sal_memset(&ds, 0, sizeof(ds));
        if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
        {
            table_type = SYS_NH_ENTRY_TYPE_NEXTHOP_8W;
            dsnh_entry_num = p_nhinfo->hdr.dsnh_entry_num *2;
        }
        else
        {
            table_type = SYS_NH_ENTRY_TYPE_NEXTHOP_4W;
            dsnh_entry_num = p_nhinfo->hdr.dsnh_entry_num;
        }
        if ((g_usw_nh_master[lchip]->bind_ldp && (SYS_NH_TYPE_IP_TUNNEL == p_nhinfo->hdr.nh_entry_type)
            && sys_usw_nh_get_offset_ref_cnt(lchip, p_nhinfo->hdr.dsnh_offset))
        || CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW))
        {
            free_hw = 0;
        }
        if (free_hw)
        {
            CTC_ERROR_RETURN(sys_usw_nh_set_asic_table(lchip, table_type, p_nhinfo->hdr.dsnh_offset, &ds));
            CTC_ERROR_RETURN(sys_usw_nh_set_glb_nh_offset(lchip, p_nhinfo->hdr.dsnh_offset, dsnh_entry_num , FALSE));
        }
    }

    p_nhinfo->hdr.dsnh_entry_num = 0;
    CTC_UNSET_FLAG(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W);
    return CTC_E_NONE;
}


int32
sys_usw_nh_copy_nh_entry_flags(uint8 lchip, sys_nh_info_com_hdr_t *p_old_hdr, sys_nh_info_com_hdr_t *p_new_hdr )
{

    sal_memcpy(p_new_hdr, p_old_hdr, sizeof(sys_nh_info_com_hdr_t));

    p_new_hdr->nh_entry_flags = 0;
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
    {
       CTC_SET_FLAG((p_new_hdr->nh_entry_flags), SYS_NH_INFO_FLAG_USE_DSNH8W);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_RSV_DSNH))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_RSV_DSNH);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_SHARE_DSNH))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_SHARE_DSNH);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_REPLI_EN))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_REPLI_EN);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_PORT))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_PORT);
    }
    if (CTC_FLAG_ISSET(p_old_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW);
    }

    return CTC_E_NONE;
}
int32
sys_usw_nh_copy_nh_entry_flags2(uint8 lchip, uint32  nh_entry_flags, sys_nh_info_com_hdr_t *p_new_hdr )
{

    p_new_hdr->nh_entry_flags = 0;

    /*fwd to unrsv flag*/
    if (CTC_FLAG_ISSET(nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_EGRESS_EDIT_MODE);
    }

    if (CTC_FLAG_ISSET(nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD);
    }
    if (CTC_FLAG_ISSET(nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1);
    }
    if (CTC_FLAG_ISSET(nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W);
    }
    if (CTC_FLAG_ISSET(nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_LOOP_USED);
    }
    if (CTC_FLAG_ISSET(nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW))
    {
       CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_NO_HW);
    }
     CTC_SET_FLAG(p_new_hdr->nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV);
    return CTC_E_NONE;
}

int32
sys_usw_nh_get_emcp_if_l2edit_offset(uint8 lchip, uint32* p_l2edit_offset)
{
    *p_l2edit_offset = g_usw_nh_master[lchip]->ecmp_if_resolved_l2edit;
    return CTC_E_NONE;
}

int32
sys_usw_nh_get_ipmc_dsnh_offset(uint8 lchip, uint16 l3ifid, uint32 logic_port, uint8 mtu_no_chk, uint32* p_dsnh_offset)
{
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint8 is_hybrid = 0;

    if ( MCHIP_CAP(SYS_CAP_L3IF_RSV_L3IF_ID) == l3ifid )
    {
        CTC_ERROR_RETURN(_sys_usw_nh_get_resolved_offset(lchip,
                                 SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH, p_dsnh_offset));
        return CTC_E_NONE;
    }

    if (l3ifid > (MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM)-1))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [L3if] Invalid interface ID! \n");
        return CTC_E_BADID;

    }

    is_hybrid = sys_usw_nh_is_xgpon_hybrid(lchip, logic_port);
    if (((0 == is_hybrid) && (p_nh_master->ipmc_dsnh_offset[l3ifid] == 0))
        || ((1 == is_hybrid) && (p_nh_master->pon_ipmc_dsnh_offset[l3ifid] == 0)))
    {
        sys_nh_param_dsnh_t dsnh_param;
        sys_l3if_prop_t l3if_prop;
        sys_dsl2edit_eth_t   dsl2edit3w;

        sal_memset(&dsnh_param, 0, sizeof(sys_nh_param_dsnh_t));
        sal_memset(&dsl2edit3w, 0, sizeof(dsl2edit3w));

        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_L3IF, 1);

        l3if_prop.l3if_id = l3ifid;
        CTC_ERROR_RETURN(sys_usw_l3if_get_l3if_info(lchip, 1, &l3if_prop));
        dsnh_param.l2edit_ptr = 0;
        dsnh_param.l3edit_ptr = 0;
        dsnh_param.dest_vlan_ptr = l3if_prop.vlan_ptr;
        dsnh_param.dsnh_type = SYS_NH_PARAM_DSNH_TYPE_IPMC;
        dsnh_param.mtu_no_chk = mtu_no_chk;

        if (is_hybrid)
        {
            dsl2edit3w.ds_type = SYS_NH_DS_TYPE_L2EDIT;
            dsl2edit3w.l2_rewrite_type = g_usw_nh_master[lchip]->rewrite_type[SYS_NH_ENTRY_TYPE_L2EDIT_INNER_SWAP];
            dsl2edit3w.derive_mcast_mac_for_ip = 1;
            dsl2edit3w.is_8w = 1;
            dsl2edit3w.update_mac_sa = 1;
            CTC_ERROR_RETURN(sys_usw_nh_add_l2edit(lchip, &dsl2edit3w,
                                        SYS_NH_ENTRY_TYPE_L2EDIT_INNER_SWAP, &dsnh_param.l2edit_ptr));
        }
        else if (l3if_prop.cvlan_id)
        {
            dsl2edit3w.output_vid = l3if_prop.vlan_id;
            dsl2edit3w.output_vlan_is_svlan = 1;
            dsl2edit3w.derive_mcast_mac_for_ip = 1;
            CTC_ERROR_RETURN(sys_usw_nh_add_l2edit(lchip, &dsl2edit3w,
                                        SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, &dsnh_param.l2edit_ptr));
        }
        else if ((DRV_IS_TMM(lchip) || DRV_IS_TMG(lchip)))
        {
            dsnh_param.l2edit_ptr = g_usw_nh_master[lchip]->rsv_l2edit_ptr;
        }
        if (0 == is_hybrid)
        {
            CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 1,
                                                       &dsnh_param.dsnh_offset));
            CTC_ERROR_RETURN(sys_usw_nh_write_entry_dsnh4w(lchip, &dsnh_param));
            p_nh_master->ipmc_dsnh_offset[l3ifid] = dsnh_param.dsnh_offset;
        }
        else
        {
            ctc_vlan_egress_edit_info_t vlan_info;
            sal_memset(&vlan_info, 0, sizeof(vlan_info));
            dsnh_param.p_vlan_info = &vlan_info;
            if (l3if_prop.vlan_id)
            {
                vlan_info.svlan_edit_type = CTC_VLAN_EGRESS_EDIT_REPLACE_VLAN;
                CTC_SET_FLAG(vlan_info.edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID);
                vlan_info.output_svid = l3if_prop.vlan_id;
            }
            if (l3if_prop.cvlan_id)
            {
                vlan_info.cvlan_edit_type = CTC_VLAN_EGRESS_EDIT_INSERT_VLAN;

                CTC_SET_FLAG(vlan_info.edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID);
                vlan_info.output_cvid = l3if_prop.cvlan_id;
            }
            dsnh_param.inner_l2edit_ptr = dsnh_param.l2edit_ptr;
            dsnh_param.l2edit_ptr = SYS_NH_GEMPORT_MAP(logic_port);
            dsnh_param.logic_port = logic_port;
            CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, 1,
                                                       &dsnh_param.dsnh_offset));
            CTC_ERROR_RETURN(sys_usw_nh_write_entry_dsnh8w(lchip, &dsnh_param));
            p_nh_master->pon_ipmc_dsnh_offset[l3ifid] = dsnh_param.dsnh_offset;
        }
        *p_dsnh_offset = dsnh_param.dsnh_offset;
    }
    else
    {
        if (0 == is_hybrid)
        {
            *p_dsnh_offset = p_nh_master->ipmc_dsnh_offset[l3ifid];
        }
        else
        {
            DsNextHop8W_m dsnh_8w;
            CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, p_nh_master->pon_ipmc_dsnh_offset[l3ifid], &dsnh_8w));
            if (logic_port != GetDsNextHop8W(V, logicDestPort_f,  &dsnh_8w))
            {
                return CTC_E_INVALID_PORT;
            }
            *p_dsnh_offset = p_nh_master->pon_ipmc_dsnh_offset[l3ifid];
        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_check_max_glb_nh_offset(uint8 lchip, uint32 offset)
{
    if (g_usw_nh_master[lchip]->pkt_nh_edit_mode == SYS_NH_EDIT_MODE_USER_DEF
        && (SYS_USW_NH_DSNH_OFFSET_VALID(offset) >= g_usw_nh_master[lchip]->max_glb_nh_offset)
        &&(g_usw_nh_master[lchip]->max_glb_nh_offset != 0))
    {
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_check_max_glb_met_offset(uint8 lchip, uint32 offset)
{
    if (offset >= g_usw_nh_master[lchip]->max_glb_met_offset)
    {
        return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_check_glb_nh_offset(uint8 lchip, uint32 start_offset, uint32 entry_num,
                                     bool should_not_inuse)
{
    uint32* p_bmp = NULL;
    uint32 curr_offset = 0;
    uint32 i = 0;

    if (NULL == (p_bmp = g_usw_nh_master[lchip]->p_occupid_nh_offset_bmp))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
			return CTC_E_NOT_INIT;

    }

    if (0 == entry_num)
    {
        return CTC_E_NONE;
    }

    for (i = 0; i < entry_num; i++)
    {
        curr_offset = SYS_USW_NH_DSNH_OFFSET_VALID(start_offset) + i;
        if (should_not_inuse && CTC_FLAG_ISSET(p_bmp[((curr_offset) >> BITS_SHIFT_OF_WORD)],
                                               (1 << (curr_offset & BITS_MASK_OF_WORD))))
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Global DsNexthop offset or GroupId is used in other nexthop cant re-use it \n");
			return CTC_E_IN_USE;

        }

        if ((!should_not_inuse) && (!CTC_FLAG_ISSET(p_bmp[((curr_offset) >> BITS_SHIFT_OF_WORD)],
                                                    (1 << (curr_offset & BITS_MASK_OF_WORD)))))
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Global DsNexthop offset or GroupId isnt used  cant free it \n");
			return CTC_E_IN_USE;

        }
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_set_glb_nh_offset(uint8 lchip, uint32 start_offset, uint32 entry_num, bool is_set)
{
    uint32* p_bmp = NULL;
    uint32 curr_offset = 0;
    int32 i = 0;

    if (0 == entry_num)
    {
        return CTC_E_NONE;
    }

    if ((SYS_USW_NH_DSNH_OFFSET_VALID(start_offset) + entry_num) > g_usw_nh_master[lchip]->max_glb_nh_offset)
    {
        return CTC_E_INVALID_PARAM;
    }

    if (NULL == (p_bmp = g_usw_nh_master[lchip]->p_occupid_nh_offset_bmp))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;
    }

    for (i = 0; i < entry_num; i++)
    {
        curr_offset = SYS_USW_NH_DSNH_OFFSET_VALID(start_offset) + i;
        if (is_set)
        {
            CTC_SET_FLAG(p_bmp[(curr_offset >> BITS_SHIFT_OF_WORD)],
                         (1 << (curr_offset & BITS_MASK_OF_WORD)));
        }
        else
        {
            CTC_UNSET_FLAG(p_bmp[(curr_offset >> BITS_SHIFT_OF_WORD)],
                           (1 << (curr_offset & BITS_MASK_OF_WORD)));
        }
    }

    return CTC_E_NONE;
}


int32
sys_usw_nh_merge_dsfwd_disable(uint8 lchip, uint32 nhid, uint8 feature)
{
    sys_nh_info_com_t* p_nh_info = NULL;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info))

    if (!p_nh_info )
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Nexthop not exist \n");
        return CTC_E_NOT_EXIST;
    }
    switch (p_nh_info->hdr.nh_entry_type )
    {
        case SYS_NH_TYPE_IPUC:
            {
                sys_nh_info_ipuc_t* p_ipuc_info = (sys_nh_info_ipuc_t*)p_nh_info;
                if (p_ipuc_info->pd->bind_data)
                {
                    mem_free(p_ipuc_info->pd->bind_data);
                    p_ipuc_info->pd->bind_data = NULL;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop]Host nexthop update to dsfwd. \n");
                }
            }
            break;
        case SYS_NH_TYPE_IP_TUNNEL:
            {
                sys_nh_info_ip_tunnel_t* p_ip_tunnel_info = (sys_nh_info_ip_tunnel_t*)p_nh_info;
                if (p_ip_tunnel_info->bind_data)
                {
                    mem_free(p_ip_tunnel_info->bind_data);
                    p_ip_tunnel_info->bind_data = NULL;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop]IP-Tunnel nexthop update to dsfwd. \n");
                    return CTC_E_NONE;
                }
            }
            break;
        case SYS_NH_TYPE_MPLS:
            {
                sys_nh_info_mpls_t* p_mpls_info = (sys_nh_info_mpls_t*)p_nh_info;
                if (p_mpls_info->pd->bind_data)
                {
                    mem_free(p_mpls_info->pd->bind_data);
                    p_mpls_info->pd->bind_data = NULL;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop]Host nexthop update to dsfwd. \n");
                }

            }
            break;
        case SYS_NH_TYPE_TRILL:
            {
                sys_nh_info_trill_t* p_trill_info = (sys_nh_info_trill_t*)p_nh_info;
                if (p_trill_info->bind_data)
                {
                    mem_free(p_trill_info->bind_data);
                    p_trill_info->bind_data = NULL;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop]Trill nexthop update to dsfwd. \n");
                }
            }
            break;
        case SYS_NH_TYPE_MISC:
            {
                sys_nh_info_misc_t* p_misc_info = (sys_nh_info_misc_t*)p_nh_info;
                if (p_misc_info->bind_data)
                {
                    mem_free(p_misc_info->bind_data);
                    p_misc_info->bind_data = NULL;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop]Misc nexthop update to dsfwd. \n");
                }
            }
            break;
        case SYS_NH_TYPE_APS:
            {
                sys_nh_info_aps_t* p_aps_info = (sys_nh_info_aps_t*)p_nh_info;
                if (p_aps_info->bind_data)
                {
                    mem_free(p_aps_info->bind_data);
                    p_aps_info->bind_data = NULL;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop]APS nexthop update to dsfwd. \n");
                }
            }
            break;
        case SYS_NH_TYPE_SRV6:
            {
                sys_nh_info_srv6_t* p_srv6_info = (sys_nh_info_srv6_t*)p_nh_info;
                if (p_srv6_info->bind_data)
                {
                    mem_free(p_srv6_info->bind_data);
                    p_srv6_info->bind_data = NULL;
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " [Nexthop]SRv6 nexthop update to dsfwd. \n");
                }
            }
            break;
        default:
            break;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_update_oam_ref_info(uint8 lchip, void* p_nhinfo, sys_nh_oam_info_t* p_oam_info, uint8 is_add)
{
    sys_nh_ref_oam_node_t* p_head = NULL;
    sys_nh_ref_oam_node_t* p_curr = NULL;
    sys_nh_ref_oam_node_t* p_nh_ref_list_node = NULL;
    sys_nh_ref_oam_node_t* p_prev = NULL;
    sys_nh_info_mpls_t* p_mpls_nh = NULL;
    sys_nh_info_ipuc_t* p_ipuc_nh = NULL;
    uint8 find_flag = 0;
    sys_nh_info_mpls_t* p_mpls_info = NULL;
    p_mpls_info = (sys_nh_info_mpls_t*)p_nhinfo;
    if (p_mpls_info->hdr.nh_entry_type == SYS_NH_TYPE_MPLS)
    {
        p_mpls_nh = (sys_nh_info_mpls_t*)p_nhinfo;
        p_curr = p_mpls_nh->pd->oam_list;
    }
    else if (p_mpls_info->hdr.nh_entry_type == SYS_NH_TYPE_IPUC)
    {
        p_ipuc_nh = (sys_nh_info_ipuc_t*)p_nhinfo;
        p_curr = p_ipuc_nh->pd->oam_list;
    }
    else
    {
        return CTC_E_INVALID_CONFIG;
    }

    p_head = p_curr;
    if (is_add)
    {
        while (p_curr)
        {
            if ((p_curr->ref_oam.mep_index == p_oam_info->mep_index) && (p_curr->ref_oam.mep_type == p_oam_info->mep_type)
                &&(p_curr->ref_oam.mep_lchip == lchip))
            {
                find_flag = 1;
                p_curr->ref_oam.ref_cnt++;
                break;
            }
            p_curr = p_curr->p_next;
        }

        if (find_flag == 0)
        {
            p_nh_ref_list_node = (sys_nh_ref_oam_node_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_ref_oam_node_t));
            if (p_nh_ref_list_node == NULL)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
                return CTC_E_NO_MEMORY;
            }

            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Add mep info, mep_type:%d, mep_index:%d, ref_cnt:%u\n",
                           p_oam_info->mep_type, p_oam_info->mep_index, p_oam_info->ref_cnt);
            sal_memset(p_nh_ref_list_node, 0, sizeof(sys_nh_ref_oam_node_t));
            p_nh_ref_list_node->ref_oam.mep_index = p_oam_info->mep_index;
            p_nh_ref_list_node->ref_oam.mep_type = p_oam_info->mep_type;
            p_nh_ref_list_node->ref_oam.mep_lchip = lchip;
            p_nh_ref_list_node->ref_oam.ref_cnt++;
            p_nh_ref_list_node->p_next = p_head;
            p_head = p_nh_ref_list_node;
            if (p_mpls_info->hdr.nh_entry_type == SYS_NH_TYPE_MPLS)
            {
                ((sys_nh_info_mpls_t*)p_nhinfo)->pd->oam_list = p_head;
            }
            else if (p_mpls_info->hdr.nh_entry_type == SYS_NH_TYPE_IPUC)
            {
                ((sys_nh_info_ipuc_t*)p_nhinfo)->pd->oam_list = p_head;
            }
        }
    }
    else
    {
        while (p_curr)
        {
            if ((p_curr->ref_oam.mep_index == p_oam_info->mep_index) && (p_curr->ref_oam.mep_type == p_oam_info->mep_type))
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "Delete mep info, mep_type:%d, mep_index:%d ref_cnt:%u\n",
                    p_oam_info->mep_type, p_oam_info->mep_index, p_curr->ref_oam.ref_cnt);
                if (p_curr->ref_oam.ref_cnt == 1)
                {
                    if (NULL == p_prev)
                    /*Remove first node*/
                    {
                        if (p_mpls_info->hdr.nh_entry_type == SYS_NH_TYPE_MPLS)
                        {
                            p_mpls_nh->pd->oam_list = p_curr->p_next;
                        }
                        else if (p_mpls_info->hdr.nh_entry_type == SYS_NH_TYPE_IPUC)
                        {
                            p_ipuc_nh->pd->oam_list = p_curr->p_next;
                        }
                    }
                    else
                    {
                        p_prev->p_next = p_curr->p_next;
                    }
                    mem_free(p_curr);
                }
                else
                {
                    p_curr->ref_oam.ref_cnt--;
                }
                break;
            }
            p_prev = p_curr;
            p_curr = p_curr->p_next;
        }
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_update_oam_mep(uint8 lchip, sys_nh_ref_oam_node_t* p_head, uint32 arp_id, sys_nh_info_dsnh_t* p_dsnh_info)
{
    sys_nh_ref_oam_node_t* p_curr = NULL;
    uint32 mep_index = 0;
    sys_nh_db_arp_t* p_arp = NULL;

    if (NULL == p_dsnh_info)
    {
        p_arp = (sys_usw_nh_lkup_arp_id(lchip, arp_id));
        if (NULL == p_arp)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
            return CTC_E_NOT_EXIST;
        }
    }

	p_curr = p_head;
	while (p_curr)
	{
        uint32 cmd = 0;
        ds_t ds_mep;
        ds_t ds_mep_mask;
        tbl_entry_t  tbl_entry;

        mep_index = p_curr->ref_oam.mep_index;
        lchip = p_curr->ref_oam.mep_lchip;
        if (mep_index > DRV_TABLE_MAX_INDEX(lchip, DsBfdMep_t))
        {
            return CTC_E_NONE;
        }
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Update oam mep: type:%d, mep_index:%d \n", p_curr->ref_oam.mep_type, mep_index);
        sal_memset(&ds_mep, 0, sizeof(ds_mep));
        sal_memset(&ds_mep_mask, 0xFF, sizeof(ds_mep_mask));
        cmd = DRV_IOR(DsBfdMep_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mep_index, DRV_CMD_PP_EN(cmd), &ds_mep));
        if (!p_curr->ref_oam.mep_type)
        {
            if (p_arp && p_arp->destmap_profile)
            {
                SetDsBfdMep(V, destMap_f,&ds_mep, SYS_ENCODE_ARP_DESTMAP(p_arp->destmap_profile));
            }
            else
            {
                if (NULL != p_arp)
                {
                    SetDsBfdMep(V, destMap_f,&ds_mep, SYS_ENCODE_DESTMAP(SYS_MAP_CTC_GPORT_TO_GCHIP(p_arp->gport),
                        SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_arp->gport)));
                }
                else
                {
                    DsBfdRmep_m ds_rmep;
                    DsBfdRmep_m ds_rmep_mask;
                    sal_memset(&ds_rmep, 0, sizeof(DsBfdRmep_m));
                    sal_memset(&ds_rmep_mask, 0xFF, sizeof(DsBfdRmep_m));
                    cmd = DRV_IOR(DsBfdRmep_t, DRV_ENTRY_FLAG);
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mep_index+1, DRV_CMD_PP_EN(cmd), &ds_rmep));
                    SetDsBfdRmep(V, apsBridgeEn_f,&ds_rmep, (p_dsnh_info->aps_en?1:0));
                    SetDsBfdRmep(V, apsBridgeEn_f,&ds_rmep_mask,0);
                    cmd = DRV_IOW(DsBfdRmep_t, DRV_ENTRY_FLAG);
                    tbl_entry.data_entry = (uint32*)&ds_rmep;
                    tbl_entry.mask_entry = (uint32*)&ds_rmep_mask;
                    CTC_ERROR_RETURN(DRV_IOCTL(lchip, mep_index+1, DRV_CMD_PP_EN(cmd), &tbl_entry));

                    SetDsBfdMep(V, destMap_f,&ds_mep, p_dsnh_info->dest_map);
                }
            }
            SetDsBfdMep(V, destMap_f,&ds_mep_mask, 0);
        }
        else
        {
            if (p_arp && p_arp->destmap_profile)
            {
                SetDsEthMep(V, destMap_f,&ds_mep, SYS_ENCODE_ARP_DESTMAP(p_arp->destmap_profile));
            }
            else
            {
                if (NULL != p_arp)
                {
                    SetDsEthMep(V, destMap_f,&ds_mep, SYS_ENCODE_DESTMAP(SYS_MAP_CTC_GPORT_TO_GCHIP(p_arp->gport),
                        SYS_MAP_CTC_GPORT_TO_DRV_LPORT(p_arp->gport)));
                }
                else
                {
                    SetDsEthMep(V, apsBridgeEn_f,&ds_mep, (p_dsnh_info->aps_en?1:0));
                    SetDsEthMep(V, apsBridgeEn_f, &ds_mep_mask, 0);
                    SetDsEthMep(V, destMap_f,&ds_mep, p_dsnh_info->dest_map);
                }
            }
            SetDsEthMep(V, destMap_f, &ds_mep_mask, 0);
        }
        cmd = DRV_IOW(DsBfdMep_t, DRV_ENTRY_FLAG);
        tbl_entry.data_entry = (uint32*)&ds_mep;
        tbl_entry.mask_entry = (uint32*)&ds_mep_mask;
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, mep_index, DRV_CMD_PP_EN(cmd), &tbl_entry));
		p_curr = p_curr->p_next;
    }

    return CTC_E_NONE;
}


int32
_sys_usw_nh_set_pw_working_path(uint8 lchip, uint8 is_working, sys_nh_info_aps_t* p_nh_aps_info)
{
    ds0_t  ds_edit_mpls;
    uint32 cmd = 0;
    sys_nh_info_mpls_t* p_nh_mpls_info_w = NULL;
    sys_nh_info_mpls_t* p_nh_mpls_info_p = NULL;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_nh_aps_info->w_nexthop_id , (sys_nh_info_com_t**)&p_nh_mpls_info_w));
    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_nh_aps_info->p_nexthop_id, (sys_nh_info_com_t**)&p_nh_mpls_info_p));
    if ((NULL == p_nh_mpls_info_w) || (NULL == p_nh_mpls_info_p))
    {
        return CTC_E_NONE;
    }
    if ((SYS_NH_TYPE_MPLS != p_nh_mpls_info_w->hdr.nh_entry_type) || (SYS_NH_TYPE_MPLS != p_nh_mpls_info_p->hdr.nh_entry_type))
    {
        return CTC_E_NONE;
    }

    cmd = DRV_IOR(DsL3EditMpls3W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_mpls_info_w->dsl3edit_offset, cmd, &ds_edit_mpls));
    SetDsL3EditMpls3W(V, discardType_f, &ds_edit_mpls, is_working? 0 : 1);
    SetDsL3EditMpls3W(V, discard_f,    &ds_edit_mpls, is_working? 0 : 1);
    cmd = DRV_IOW(DsL3EditMpls3W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_mpls_info_w->dsl3edit_offset, cmd, &ds_edit_mpls));

    cmd = DRV_IOR(DsL3EditMpls3W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_mpls_info_p->dsl3edit_offset, cmd, &ds_edit_mpls));
    SetDsL3EditMpls3W(V, discardType_f, &ds_edit_mpls, is_working? 1 : 0);
    SetDsL3EditMpls3W(V, discard_f,    &ds_edit_mpls, is_working? 1 : 0);
    cmd = DRV_IOW(DsL3EditMpls3W_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_mpls_info_p->dsl3edit_offset, cmd, &ds_edit_mpls));

    return CTC_E_NONE;
}



int32
_sys_usw_nh_add_dsfwd(uint8 lchip, sys_nh_info_com_t* p_com_db, sys_nh_param_dsfwd_t* dsfwd_param, uint8 is_dsfwd1)
{
    int32 ret = CTC_E_NONE;
    uint8 alloc_dsfwd = 0;
    uint32 dsfwd_offset = 0;


    if ((!CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD)) && (0 == is_dsfwd1))
    {
        if (CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1))
        {
            if (dsfwd_param->is_6w && (!CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)))
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Cannot update dsfwd from half to full! \n");
                return CTC_E_NOT_SUPPORT;
            }
        }

        CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, dsfwd_param->is_6w? SYS_NH_ENTRY_TYPE_FWD : SYS_NH_ENTRY_TYPE_FWD_HALF, 1,
                                      &dsfwd_offset));
        p_com_db->hdr.dsfwd_offset = dsfwd_offset;
        dsfwd_param->dsfwd_offset  = dsfwd_offset;
        alloc_dsfwd = 1;
    }
    else if (DRV_FROM_AT(lchip) && (!CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1)) && (1 == is_dsfwd1))
    {
        if (CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
        {
            if (dsfwd_param->is_6w && (!CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)))
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Cannot update dsfwd from half to full! \n");
                return CTC_E_NOT_SUPPORT;
            }
        }

        CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, dsfwd_param->is_6w? SYS_NH_ENTRY_TYPE_FWD1 : SYS_NH_ENTRY_TYPE_FWD_HALF1, 1,
                                      &dsfwd_offset));
        p_com_db->hdr.dsfwd1_offset = dsfwd_offset;
        dsfwd_param->dsfwd_offset  = dsfwd_offset;
        alloc_dsfwd = 1;
    }
    else
    {
        if (dsfwd_param->is_6w && (!CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)))
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "Cannot update dsfwd from half to full! \n");
            return CTC_E_NOT_SUPPORT;
        }
        dsfwd_param->dsfwd_offset  = is_dsfwd1? p_com_db->hdr.dsfwd1_offset : p_com_db->hdr.dsfwd_offset;
    }
    dsfwd_param->is_dsfwd1 = is_dsfwd1;
    CTC_ERROR_GOTO(sys_usw_nh_write_entry_dsfwd(lchip, dsfwd_param), ret, error0);
    if (is_dsfwd1)
    {
        CTC_SET_FLAG(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1);
    }
    else
    {
        CTC_SET_FLAG(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD);
    }
    p_com_db->hdr.nh_entry_flags |= (dsfwd_param->is_6w)? SYS_NH_INFO_FLAG_DSFWD_IS_6W : 0;
    return CTC_E_NONE;

error0:
    if (alloc_dsfwd)
    {
        if (is_dsfwd1)
        {
            sys_usw_nh_offset_free(lchip,  dsfwd_param->is_6w? SYS_NH_ENTRY_TYPE_FWD1 : SYS_NH_ENTRY_TYPE_FWD_HALF1, 1, p_com_db->hdr.dsfwd1_offset);
        }
        else
        {
            sys_usw_nh_offset_free(lchip,  dsfwd_param->is_6w? SYS_NH_ENTRY_TYPE_FWD : SYS_NH_ENTRY_TYPE_FWD_HALF, 1, p_com_db->hdr.dsfwd_offset);
        }
    }
    return ret;
}

int32
_sys_usw_nh_remove_dsfwd(uint8 lchip, sys_nh_info_com_t* p_com_db)
{
    sys_nh_param_dsfwd_t dsfwd_param;
    sal_memset(&dsfwd_param, 0, sizeof(sys_nh_param_dsfwd_t));
    if (CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
    {
        dsfwd_param.dsfwd_offset = p_com_db->hdr.dsfwd_offset;
        dsfwd_param.drop_pkt = 1;
        /*Write table*/
        sys_usw_nh_write_entry_dsfwd(lchip, &dsfwd_param);
        /*Free DsFwd offset*/
        sys_usw_nh_offset_free(lchip,
                               CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)? SYS_NH_ENTRY_TYPE_FWD : SYS_NH_ENTRY_TYPE_FWD_HALF, 1, p_com_db->hdr.dsfwd_offset);
        CTC_UNSET_FLAG(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD);
    }
    if (DRV_FROM_AT(lchip) && CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1))
    {
       sal_memset(&dsfwd_param, 0, sizeof(sys_nh_param_dsfwd_t));
        dsfwd_param.dsfwd_offset = p_com_db->hdr.dsfwd1_offset;
        dsfwd_param.drop_pkt = 1;
        dsfwd_param.is_dsfwd1 = 1;
        /*Write table*/
        sys_usw_nh_write_entry_dsfwd(lchip, &dsfwd_param);
        /*Free DsFwd offset*/
        sys_usw_nh_offset_free(lchip,
                               CTC_FLAG_ISSET(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)? SYS_NH_ENTRY_TYPE_FWD1 : SYS_NH_ENTRY_TYPE_FWD_HALF1, 1, p_com_db->hdr.dsfwd1_offset);
        CTC_UNSET_FLAG(p_com_db->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1);
    }
    return CTC_E_NONE;
}


#define _________ds_write________
#if 0
/**
 @brief This function is deinit nexthop module   callback function for each nexthop type
 */
int32
sys_usw_nh_global_dync_entry_set_default(uint8 lchip, uint32 min_offset, uint32 max_offset)
{

    return CTC_E_NONE;
}
#endif

int32
sys_usw_nh_mpls_add_cw(uint8 lchip, uint32 cw,
                                 uint8* cw_index,
                                 bool is_add)
{
    uint8 bit = 0;
    uint32 cmd = 0;
    uint8 free = 0;
    uint32 field_val = 0;
    sys_usw_nh_master_t* p_master = g_usw_nh_master[lchip];

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER, 1);
    if (is_add)
    {
        for (bit = 1; bit < SYS_NH_CW_NUM; bit++)
        {
            if (p_master->cw_ref_cnt[bit])
            {
                cmd = DRV_IOR(DsControlWord_t, DsControlWord_cwData_f);
                CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, bit, cmd, &field_val));

                if (field_val == cw)
                {
                    if (0xFFFF == p_master->cw_ref_cnt[bit])
                    {
                        return CTC_E_NO_RESOURCE;
                    }
                    p_master->cw_ref_cnt[bit]++;
                    *cw_index = bit;
                    return CTC_E_NONE;
                }

                break;
            }
            else if (free == 0)
            {
                free = bit;
            }

        }

        if (free != 0)
        {
            field_val = cw;
            cmd = DRV_IOW(DsControlWord_t, DsControlWord_cwData_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, free, cmd, &field_val));
            p_master->cw_ref_cnt[free]++;
            *cw_index = free;
            return CTC_E_NONE;
        }

        return CTC_E_INVALID_PARAM;

    }
    else
    {
        bit = *cw_index;
        p_master->cw_ref_cnt[bit]--;
        *cw_index = 0;
        if (p_master->cw_ref_cnt[bit] == 0)
        {
            field_val = 0;
            cmd = DRV_IOW(DsControlWord_t, DsControlWord_cwData_f);
            CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, bit, cmd, &field_val));
        }
    }

    return CTC_E_NONE;

}



STATIC int32
sys_usw_nh_dsnh_build_vlan_info(uint8 lchip, sys_nexthop_t* p_dsnh,
                                      ctc_vlan_egress_edit_info_t* p_vlan_info)
{
    if (!p_vlan_info)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid pointer \n");
			return CTC_E_INVALID_PTR;

    }

    if (CTC_FLAG_ISSET(p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF))
    {
        p_dsnh->is_leaf = 1;
    }

    if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_VLAN_SWAP_EN))
    {
        /*1. cvlan_tag_op_disable = 1*/
        p_dsnh->cvlan_tag_disable = TRUE;

        /*2. svlan_tag_op_disable = 1*/
        p_dsnh->svlan_tag_disable = TRUE;

        /*3. tagged_mode = 1*/
        p_dsnh->tagged_mode = TRUE;

        /*Unset  parametre's cvid valid bit, other with output
        cvlan id valid will be overwrited in function
        sys_usw_nh_dsnh4w_assign_vid, bug11323*/
        CTC_UNSET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID);
        CTC_UNSET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID);

        /*Swap TPID*/
        if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_TPID_SWAP_EN))
        {
            p_dsnh->tpid_swap = TRUE;
        }

        /*Swap Cos*/
        if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_COS_SWAP_EN))
        {
            p_dsnh->cos_swap = TRUE;
        }
    }
    else
    {
        switch (p_vlan_info->svlan_edit_type)
        {
        case CTC_VLAN_EGRESS_EDIT_NONE:
        case CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE:
            p_dsnh->output_svlan_id_valid = FALSE;
            CTC_UNSET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID);
            p_dsnh->svlan_tagged = TRUE;
            p_dsnh->derive_stag_cos  = 1;
            p_dsnh->stag_cfi  = 0;       /*use  raw packet's cos*/
            break;
        case CTC_VLAN_EGRESS_EDIT_INSERT_VLAN:
            p_dsnh->tagged_mode = TRUE; /*insert stag*/
            p_dsnh->svlan_tagged = TRUE;
            p_dsnh->stag_cfi  = 0;
            p_dsnh->derive_stag_cos  = 1;

            if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_SVLAN_AWARE))
            {
                p_dsnh->stag_action = 1;
            }
            break;

        case CTC_VLAN_EGRESS_EDIT_REPLACE_VLAN:
            p_dsnh->svlan_tagged = TRUE;
            p_dsnh->stag_cfi  = 0;
            p_dsnh->derive_stag_cos  = 1;
            if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_SVLAN_AWARE))
            {
                p_dsnh->stag_action = 3;
            }
            break;

        case CTC_VLAN_EGRESS_EDIT_STRIP_VLAN:
            p_dsnh->svlan_tagged = FALSE;
            if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_SVLAN_AWARE))
            {
                p_dsnh->stag_action = 2;
            }
            break;

        default:
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Egress Vlan Edit type is invalid \n");
			return CTC_E_INVALID_CONFIG;

        }

       /* stag cos opreation */
        if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_REPLACE_SVLAN_COS))
        {
            p_dsnh->replace_stag_cos    = 1;
            p_dsnh->derive_stag_cos     = 0;
            p_dsnh->stag_cos            = p_vlan_info->stag_cos & 0x7;
            p_dsnh->stag_cfi  = (p_vlan_info->stag_cos >> 3) & 1;
        }
        else if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_MAP_SVLAN_COS))
        {
            p_dsnh->derive_stag_cos     = 1;
            p_dsnh->replace_stag_cos    = 1;
        }

        switch (p_vlan_info->cvlan_edit_type)
        {
        case CTC_VLAN_EGRESS_EDIT_NONE:

            /*Don't use DsNexthop's output cvlanid*/
            p_dsnh->output_cvlan_id_valid = FALSE;
            p_dsnh->cvlan_tag_disable = FALSE;
            CTC_UNSET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID);
            break;

        case CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE:
            p_dsnh->cvlan_tag_disable = TRUE;
            break;

        case CTC_VLAN_EGRESS_EDIT_INSERT_VLAN:
            p_dsnh->output_cvlan_id_valid = TRUE;
            break;

        case CTC_VLAN_EGRESS_EDIT_REPLACE_VLAN:
            break;

        case CTC_VLAN_EGRESS_EDIT_STRIP_VLAN:
            p_dsnh->cvlan_strip = TRUE;
            break;

        default:
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Egress Vlan Edit type is invalid \n");
			return CTC_E_INVALID_CONFIG;

        }
    }
    if((CTC_VLAN_EGRESS_EDIT_NONE == p_vlan_info->cvlan_edit_type && CTC_VLAN_EGRESS_EDIT_NONE == p_vlan_info->svlan_edit_type)
        && (!CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_VLAN_SWAP_EN)))
    {
        p_dsnh->vlan_xlate_mode = 0;
    }
    return CTC_E_NONE;
}

STATIC int32
sys_usw_nh_dsnh4w_assign_vid(uint8 lchip, sys_nexthop_t* p_dsnh,
                                   ctc_vlan_egress_edit_info_t* p_vlan_info)
{
    if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID))
    {
        p_dsnh->output_cvlan_id_valid = TRUE;
        p_dsnh->output_cvlan_id = p_vlan_info->output_cvid;
    }

    if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID))
    {
        p_dsnh->output_svlan_id_valid = TRUE;
        p_dsnh->output_svlan_id= p_vlan_info->output_svid;
    }

    if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUTPUT_SVLAN_TPID_VALID))
    {
        if(p_vlan_info->svlan_tpid_index>3)
        {
            return CTC_E_INVALID_PARAM;
        }
        p_dsnh->svlan_tpid_en = TRUE;
        p_dsnh->svlan_tpid = p_vlan_info->svlan_tpid_index;
    }

    return CTC_E_NONE;
}

STATIC int32
sys_usw_nh_dsnh8w_assign_vid(uint8 lchip, sys_nexthop_t* p_dsnh8w,
                                   ctc_vlan_egress_edit_info_t* p_vlan_info)
{
    if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID))
    {
        p_dsnh8w->output_cvlan_id_valid = TRUE;
        p_dsnh8w->output_cvlan_id = p_vlan_info->output_cvid;
    }

    if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID))
    {
        p_dsnh8w->output_svlan_id_valid = TRUE;
        p_dsnh8w->output_svlan_id = p_vlan_info->output_svid;
    }

    if (CTC_FLAG_ISSET(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUTPUT_SVLAN_TPID_VALID))
    {
        if(p_vlan_info->svlan_tpid_index>3)
        {
            return CTC_E_INVALID_PARAM;
        }
        p_dsnh8w->svlan_tpid_en = TRUE;
        p_dsnh8w->svlan_tpid = p_vlan_info->svlan_tpid_index;
    }

    return CTC_E_NONE;
}

/*
   inner_edit:ptr_type
   0- L2Edit
   1- L3Edit

  outer_edit: location/type
   0/1   L3Edit (Pipe0) -->( L3Edit (Pipe1),opt)--> L2Edit(Pipe2)
   0/0   L2Edit (Pipe0) --> L3Edit(Pipe1)
   1/0   L2Edit (Pipe2)
   1/1   L3Edit (Pipe1) --> L2Edit(Pipe2)
*/

int32
sys_usw_nh_write_entry_dsnh4w(uint8 lchip, sys_nh_param_dsnh_t* p_dsnh_param)
{

    sys_nexthop_t dsnh;
    uint32 op_bridge = SYS_NH_OP_NONE;
    uint8 xgpon_en = 0;
    uint8  bpe_pe_mode = 0;

    sal_memset(&dsnh, 0, sizeof(dsnh));

    if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_L2EDIT_AS_APS_GROUP))
    {
        dsnh.aps_bridge_en = 1;
    }

    dsnh.stats_ptr  = p_dsnh_param->stats_ptr;
    dsnh.cid_valid = p_dsnh_param->cid?1:0;
    dsnh.cid       = p_dsnh_param->cid;
    dsnh.dvp_tbl_valid = p_dsnh_param->dvp_tbl_valid;

    bpe_pe_mode = (g_usw_nh_master[lchip]->bpe_en&0x1)?1:0;
    if (bpe_pe_mode && p_dsnh_param->stats_ptr)
    {
        /*bpe ecid enable, cannot support nh stats*/
        return CTC_E_INVALID_CONFIG;
    }

    if (dsnh.cid_valid && !g_usw_nh_master[lchip]->cid_use_4w)
    {
        return CTC_E_INVALID_CONFIG;
    }

    switch (p_dsnh_param->dsnh_type)
    {
    case SYS_NH_PARAM_DSNH_TYPE_IPUC:
        dsnh.mtu_check_en = !(p_dsnh_param->mtu_no_chk);

        /*IPUC only use ROUTE_COMPACT in current GB SDK*/
        if ((p_dsnh_param->l2edit_ptr == 0) && (p_dsnh_param->inner_l2edit_ptr == 0))
        {
            dsnh.payload_operation = SYS_NH_OP_ROUTE_COMPACT;
            dsnh.share_type = SYS_NH_SHARE_TYPE_MAC_DA;
            SYS_USW_NH_DSNH_ASSIGN_MACDA(dsnh, (*p_dsnh_param));
            if(CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL))
            {
                dsnh.ttl_no_dec = TRUE;
            }
            else
            {
                dsnh.ttl_no_dec = FALSE;
            }
        }
        else
        {
           SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);
           if(CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL))
           {
               dsnh.payload_operation = SYS_NH_OP_ROUTE_NOTTL;
           }
           else
           {
               dsnh.payload_operation = SYS_NH_OP_ROUTE;
           }
           dsnh.share_type = SYS_NH_SHARE_TYPE_L2EDIT_VLAN;

           dsnh.outer_edit_valid    = 1;
           dsnh.outer_edit_ptr_type = 0;/*L2edit*/
           if (p_dsnh_param->l2edit_ptr)
           {
               dsnh.outer_edit_location = 1;/*Pipe1*/
               dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
               if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM))
               {
                   /*use spme resource to edit ARP*/
                   dsnh.outer_edit_ptr_type = 1;
                   dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                   dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)? (1 << 11) : (1 << 10));
               }
           }
           else if (p_dsnh_param->inner_l2edit_ptr)
           {
               dsnh.outer_edit_location = 0;/*Pipe0*/
               dsnh.outer_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
           }

           /*for phy if vlan, no use any more*/
           if(p_dsnh_param->p_vlan_info
              && CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID))
               {
                dsnh.output_svlan_id_valid = p_dsnh_param->p_vlan_info->output_svid != 0;
                dsnh.output_svlan_id = p_dsnh_param->p_vlan_info->output_svid;
               }
        }
        dsnh.dest_vlan_ptr = p_dsnh_param->dest_vlan_ptr;
        dsnh.strip_l2_hdr = 1;
        dsnh.use_packet_ttl = p_dsnh_param->use_ttl_from_pkt;
        dsnh.bypass_ldp = 0;
        if (DRV_FROM_AT(lchip))
        {
            dsnh.dvp_tbl_valid = 1;
        }
        break;

    case SYS_NH_PARAM_DSNH_TYPE_IPMC:
        dsnh.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        dsnh.svlan_tagged = 1;
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh.payload_operation = SYS_NH_OP_ROUTE_COMPACT;
        dsnh.share_type = SYS_NH_SHARE_TYPE_MAC_DA;
        dsnh.strip_l2_hdr = 1;
        if (p_dsnh_param->l2edit_ptr)
        {
            dsnh.payload_operation = SYS_NH_OP_ROUTE;
            dsnh.share_type = SYS_NH_SHARE_TYPE_L2EDIT_VLAN;
            dsnh.outer_edit_valid    = 1;
            dsnh.outer_edit_ptr_type = 0;/*L2edit*/
            dsnh.outer_edit_location = 0;/*Pipe0*/
            dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
        }

        break;

    case SYS_NH_PARAM_DSNH_TYPE_BRGUC:
        /*Set default cos action*/
        SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh);
        dsnh.svlan_tagged = 1;
        dsnh.dest_vlan_ptr = p_dsnh_param->dest_vlan_ptr;   /*value 0 means use srcvlanPtr*/
        dsnh.payload_operation = CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_SWAP_MAC) ?
            SYS_NH_OP_NONE : SYS_NH_OP_BRIDGE;
        dsnh.logic_dest_port     = p_dsnh_param->logic_port;
        dsnh.logic_port_check    = p_dsnh_param->logic_port_check;
        dsnh.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
        sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
        if (xgpon_en)
        {

            if (p_dsnh_param->l2edit_ptr)
            {
                dsnh.vlan_xlate_mode = 0;
                dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
                dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
            }
            else
            {
                if (DRV_FROM_TM(lchip) && p_dsnh_param->p_vlan_info && CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_SERVICE_QUEUE_FLAG)
                && CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF))
                {
                        dsnh.vlan_xlate_mode = 0;
                }
                else
                {
                    dsnh.vlan_xlate_mode = 1;       /*humber mode*/
                }
            }
            if (p_dsnh_param->l3edit_ptr && DRV_IS_DUET2(lchip))
            {
                dsnh.inner_edit_ptr_type = 1;
                dsnh.inner_edit_ptr = g_usw_nh_master[lchip]->mpls_edit_offset + p_dsnh_param->l3edit_ptr -1;
            }
        }
        else
        {
            dsnh.vlan_xlate_mode = 1;       /*humber mode*/
            if(p_dsnh_param->l2edit_ptr)
            {
                dsnh.share_type = SYS_NH_SHARE_TYPE_L2EDIT_VLAN;
                dsnh.outer_edit_valid    = 1;
                dsnh.outer_edit_ptr_type = 0;
                dsnh.outer_edit_location = 0;
                dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
            }
        }
        if (p_dsnh_param->p_vlan_info)
        {
            if (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_STATS_EN))
            {
                CTC_ERROR_RETURN(sys_usw_flow_stats_get_statsptr(lchip, p_dsnh_param->p_vlan_info->stats_id, &(dsnh.stats_ptr)));
                if (bpe_pe_mode && dsnh.stats_ptr)
                {
                    /*bpe ecid enable, cannot support nh stats*/
                    return CTC_E_INVALID_CONFIG;
                }
            }
            if (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF))
            {
                dsnh.is_leaf = 1;
            }
             if (p_dsnh_param->p_vlan_info->flag & CTC_VLAN_NH_MTU_CHECK_EN)
            {
                dsnh.mtu_check_en = 1;
            }
            if(CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag,CTC_VLAN_NH_HORIZON_SPLIT_EN))
            {
                dsnh.payload_operation = SYS_NH_OP_BRIDGE_VPLS;
            }
            else if (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_PASS_THROUGH))
            {
                dsnh.payload_operation = SYS_NH_OP_BRIDGE_INNER;
            }
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, &dsnh, p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh4w_assign_vid(lchip, &dsnh, p_dsnh_param->p_vlan_info));
        }
        break;

    case SYS_NH_PARAM_DSNH_TYPE_BYPASS:
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh.payload_operation = SYS_NH_OP_NONE;
        dsnh.vlan_xlate_mode = 1;    /*humber mode*/
        break;

    case SYS_NH_PARAM_DSNH_TYPE_MPLS_PHP: /*PHP */

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_PHP_SHORT_PIPE))
        {
            dsnh.payload_operation = SYS_NH_OP_ROUTE_NOTTL;
            dsnh.use_packet_ttl = 1;
        }
        else
        {
            dsnh.payload_operation = SYS_NH_OP_ROUTE;
        }

        dsnh.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        dsnh.dest_vlan_ptr = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);
        dsnh.share_type = SYS_NH_SHARE_TYPE_L2EDIT_VLAN;
        dsnh.outer_edit_valid    = 1;
        dsnh.outer_edit_ptr_type = 0;/*L2edit*/
        if (p_dsnh_param->l2edit_ptr)
        {
            dsnh.outer_edit_location = 1;/*Pipe2*/
            dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
            if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM))
            {
                /*use spme resource to edit ARP*/
                dsnh.outer_edit_ptr_type = 1;
                dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)?(1 << 11):(1 << 10));
            }
        }
        else if (p_dsnh_param->inner_l2edit_ptr)
        {
            dsnh.outer_edit_location = 0;/*Pipe0*/
            dsnh.outer_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
        }
        /*for phy if vlan, no use any more*/
        if(p_dsnh_param->p_vlan_info
              && CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID))
        {
                dsnh.output_svlan_id_valid = p_dsnh_param->p_vlan_info->output_svid != 0;
                dsnh.output_svlan_id = p_dsnh_param->p_vlan_info->output_svid;
        }
        dsnh.strip_l2_hdr = 1;
        break;
    case SYS_NH_PARAM_DSNH_TYPE_MPLS_OP_NONE:   /* mpls switch*/
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Should use DsNexthop8W table \n");
			return CTC_E_INVALID_CONFIG;

        break;

    case SYS_NH_PARAM_DSNH_TYPE_MPLS_PUSH_OP_NONE: /*Swap  label on LSR /Pop label and do   label  Swap on LER*/
        dsnh.payload_operation = SYS_NH_OP_NONE;
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);

        if(p_dsnh_param->lspedit_ptr || (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_L2EDIT_AS_APS_GROUP)))
        {
            dsnh.outer_edit_location = (p_dsnh_param->spme_mode)?1:0;
            dsnh.outer_edit_ptr_type = 1;/*Pipe0: L3edit*/
            dsnh.outer_edit_ptr = p_dsnh_param->lspedit_ptr;
        }
        else
        {
            dsnh.outer_edit_location = p_dsnh_param->loop_edit?0:1;
            dsnh.outer_edit_ptr_type = 0;/*Pipe0: L2edit*/
            dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
            if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && !p_dsnh_param->loop_edit)
            {
                /*use spme resource to edit ARP*/
                dsnh.outer_edit_ptr_type = 1;
                dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)?(1 << 11):(1 << 10));
            }
        }

        dsnh.inner_edit_ptr_type = 1;/*L3Edit*/
        dsnh.inner_edit_ptr = p_dsnh_param->l3edit_ptr;


        break;

    case SYS_NH_PARAM_DSNH_TYPE_MPLS_PUSH_OP_ROUTE: /* (L3VPN/FTN)*/
        dsnh.payload_operation = SYS_NH_OP_ROUTE;
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);

        dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;

        if (dsnh.aps_bridge_en)
        {
            dsnh.outer_edit_location = 0;
            dsnh.outer_edit_ptr_type = 1;
            dsnh.outer_edit_ptr = p_dsnh_param->lspedit_ptr;/*aps group*/
        }
        else
        {
            if (p_dsnh_param->spme_mode)
            {
                dsnh.outer_edit_location = 1;
                dsnh.outer_edit_ptr_type = 1;
                dsnh.outer_edit_ptr = p_dsnh_param->lspedit_ptr;/*Pipe0: L3edit*/
            }
            else
            {
                if(p_dsnh_param->lspedit_ptr) /*LSP+ARP*/
                {
                    dsnh.outer_edit_location = 0;
                    dsnh.outer_edit_ptr_type = 1;
                    dsnh.outer_edit_ptr = p_dsnh_param->lspedit_ptr;/*Pipe0: L3edit*/
                }
                else /*ARP or loop*/
                {
                    dsnh.outer_edit_location = p_dsnh_param->loop_edit?0:1; /*for loop, using pipe0*/
                    dsnh.outer_edit_ptr_type = 0;
                    dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;/*Pipe3: l2edti*/
                    if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && !p_dsnh_param->loop_edit)
                    {
                        /*use spme resource to edit ARP*/
                        dsnh.outer_edit_ptr_type = 1;
                        dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                        dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)? (1 << 11) : (1 << 10));
                    }
                }
            }

        }

        dsnh.inner_edit_ptr_type = 1;/* L3Edit*/
        dsnh.inner_edit_ptr = p_dsnh_param->l3edit_ptr;

        dsnh.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        dsnh.strip_l2_hdr = 1;
        dsnh.is_encap = 1;
        break;

    case SYS_NH_PARAM_DSNH_TYPE_MPLS_PUSH_OP_L2VPN:
        if (p_dsnh_param->hvpls)
        {
            op_bridge = SYS_NH_OP_BRIDGE_INNER;
        }
        else
        {
            op_bridge = SYS_NH_OP_BRIDGE_VPLS;
        }

        if (p_dsnh_param->spme_mode)
        {
            op_bridge = SYS_NH_OP_NONE;
        }

        dsnh.vlan_xlate_mode = 1;       /*humber mode*/
        dsnh.payload_operation = op_bridge;
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        dsnh.cw_index = p_dsnh_param->cw_index;
        dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;

        if (p_dsnh_param->spme_mode)
        {
            dsnh.outer_edit_location = 0;
            dsnh.outer_edit_ptr_type = 1;
            dsnh.outer_edit_ptr = p_dsnh_param->l3edit_ptr; /*Pipe0: L3edit*/

            dsnh.inner_edit_ptr_type = 0; /* L3Edit(1)*/
            dsnh.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
        }
        else
        {
            if(p_dsnh_param->lspedit_ptr || (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_L2EDIT_AS_APS_GROUP)))
            {
                dsnh.outer_edit_location = 0;
                dsnh.outer_edit_ptr_type = 1;
                dsnh.outer_edit_ptr = p_dsnh_param->lspedit_ptr; /*Pipe0: L3edit*/
            }
            else
            {
                dsnh.outer_edit_location = p_dsnh_param->loop_edit?0:1;
                dsnh.outer_edit_ptr_type = 0;
                dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr; /*Pipe0: L2edit*/
                if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && !p_dsnh_param->loop_edit)
                {
                    /*use spme resource to edit ARP*/
                    dsnh.outer_edit_ptr_type = 1;
                    dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                    dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)? (1 << 11) : (1 << 10));
                }
            }

            if (p_dsnh_param->loop_edit && p_dsnh_param->inner_l2edit_ptr)
            {
                /*do inner l2 edit*/
                dsnh.inner_edit_ptr_type = 0; /* L2Edit(1)*/
                dsnh.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
            }
            else
            {
                dsnh.inner_edit_ptr_type = 1; /* L3Edit(1)*/
                dsnh.inner_edit_ptr = p_dsnh_param->l3edit_ptr;
            }

        }

        if(!p_dsnh_param->spme_mode)
        {
            if (p_dsnh_param->p_vlan_info &&
                ((CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID)) ||
                 (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID))))
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] Should use DsNexthop8W table \n");
    			return CTC_E_INVALID_CONFIG;

            }
            else if(p_dsnh_param->p_vlan_info)
            {
                if (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF) || p_dsnh_param->is_leaf)
                {
                    dsnh.is_leaf = 1;
                }

                /*Set default cos action*/
                SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh);
                CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, &dsnh, p_dsnh_param->p_vlan_info));
            }
        }
        dsnh.is_encap = 1;
        break;

    case SYS_NH_PARAM_DSNH_TYPE_RSPAN:
        dsnh.vlan_xlate_mode = 1;    /*humber mode*/
        dsnh.tagged_mode = 1;
        dsnh.svlan_tagged = 1;
        dsnh.mirror_tag_add = 1;
        dsnh.derive_stag_cos = 1;    /*restore vlantag for mirror*/
        dsnh.replace_ctag_cos = 1;   /*add rspan vlan id*/
        dsnh.output_svlan_id_valid = 1;
        dsnh.output_svlan_id = p_dsnh_param->p_vlan_info?(p_dsnh_param->p_vlan_info->output_svid & 0xFFF):0;
        dsnh.dest_vlan_ptr = p_dsnh_param->dest_vlan_ptr;
        dsnh.payload_operation = SYS_NH_OP_MIRROR;
        dsnh.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
        break;

    case SYS_NH_PARAM_DSNH_TYPE_IPTUNNEL:

        dsnh.payload_operation = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_NONE)) ?
            SYS_NH_OP_NONE  : ((CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL)) ?
            SYS_NH_OP_ROUTE_NOTTL : SYS_NH_OP_ROUTE);

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_BRIDGE))
        {
            dsnh.payload_operation = p_dsnh_param->hvpls?SYS_NH_OP_BRIDGE_INNER: SYS_NH_OP_BRIDGE_VPLS;
        }

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_STRIP_VLAN))
        {
            dsnh.svlan_tagged = FALSE;
            dsnh.vlan_xlate_mode = 1;       /*humber mode*/
        }
        else
        {
           dsnh.svlan_tagged = TRUE;
        }
        dsnh.bridge_inner = 1; /*From TM.MX, bridge inner from DsNextHop and default do bridge inner*/
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);

        dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_NAT) && DRV_FROM_TMM(lchip))
        {
            dsnh.outer_edit_location = 0;
            dsnh.outer_edit_ptr_type = 1;
            dsnh.outer_edit_ptr = p_dsnh_param->l3edit_ptr;  /*Pipe0 L3edit*/
            dsnh.inner_edit_ptr_type = 0;
            dsnh.inner_edit_ptr = 0;
        }
        else if (p_dsnh_param->inner_l2edit_ptr)
        { /*outer L2Edit*/
            dsnh.outer_edit_location = 0;
            dsnh.outer_edit_ptr_type = 1;
            dsnh.outer_edit_ptr = p_dsnh_param->l3edit_ptr;  /*Pipe0 L3edit*/

            dsnh.inner_edit_ptr_type = 0;
            dsnh.inner_edit_ptr = p_dsnh_param->l2edit_ptr;  /*inner L2edit*/

        }
        else
        {
            dsnh.outer_edit_location = 1;
            dsnh.outer_edit_ptr_type = 0;
            dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;  /*outer L2edit*/
            dsnh.inner_edit_ptr_type = 1;
            dsnh.inner_edit_ptr = p_dsnh_param->l3edit_ptr;  /*L3 edit*/
            if (p_dsnh_param->loop_edit)
            {
                dsnh.outer_edit_location = 0;
            }
            if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && !p_dsnh_param->loop_edit)
            {
                /*use spme resource to edit ARP*/
                dsnh.outer_edit_ptr_type = 1;
                dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)?(1 << 11):(1 << 10));
            }
        }
        dsnh.is_encap = 1;
        dsnh.mtu_check_en = FALSE;
        dsnh.strip_l2_hdr = p_dsnh_param->strip_l2_hdr;
        dsnh.use_packet_ttl = p_dsnh_param->use_ttl_from_pkt;
        break;
    case SYS_NH_PARAM_DSNH_TYPE_OVERLAY_VNI:
        dsnh.payload_operation = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL) ?
        SYS_NH_OP_ROUTE_NOTTL : SYS_NH_OP_ROUTE);
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_BRIDGE))
        {
            dsnh.payload_operation = p_dsnh_param->hvpls? SYS_NH_OP_BRIDGE_INNER : SYS_NH_OP_BRIDGE_VPLS;
        }
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_STRIP_VLAN))
        {
            dsnh.svlan_tagged = FALSE;
            dsnh.vlan_xlate_mode = 1;       /*humber mode*/
        }
        else
        {
            dsnh.svlan_tagged = TRUE;
        }
        dsnh.bridge_inner = 1; /*From TM.MX, bridge inner from DsNextHop and default do bridge inner*/
        if (p_dsnh_param->p_vlan_info)
        {
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, &dsnh, p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh4w_assign_vid(lchip, &dsnh, p_dsnh_param->p_vlan_info));
            dsnh.vlan_xlate_mode = 0; /*misc mode*/
            dsnh.dest_vlan_ptr = p_dsnh_param->dest_vlan_ptr;
        }

        dsnh.outer_edit_location = 0;
        dsnh.inner_edit_ptr_type = 0;
        dsnh.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr; /*inner L2edit*/

        dsnh.share_type = SYS_NH_SHARE_TYPE_L2EDIT_VLAN;

        dsnh.mtu_check_en = FALSE;
        dsnh.strip_l2_hdr = p_dsnh_param->strip_l2_hdr;

        break;
    case SYS_NH_PARAM_DSNH_TYPE_SRV6:
        dsnh.payload_operation =   (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL))?
                                                                SYS_NH_OP_ROUTE_NOTTL: SYS_NH_OP_ROUTE;
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_BRIDGE))
        {
            dsnh.payload_operation = p_dsnh_param->hvpls?SYS_NH_OP_BRIDGE_INNER: SYS_NH_OP_BRIDGE_VPLS;
        }
        dsnh.svlan_tagged = TRUE;
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);
        dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
        if (p_dsnh_param->loop_edit)
        {
            dsnh.outer_edit_ptr_type = 0;
            dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr; /*loop edit*/
        }
        else if((0 == p_dsnh_param->inner_l2edit_ptr) && (0 == p_dsnh_param->dvp_tbl_valid))
        {
            dsnh.outer_edit_ptr_type = 1;
            dsnh.outer_edit_ptr = p_dsnh_param->l3edit_ptr; /*ipv6 tunnel edit*/

        }
        else
        {
            if (0 == p_dsnh_param->dvp_tbl_valid)
            {
                dsnh.outer_edit_ptr_type = 1;
                dsnh.outer_edit_ptr = DRV_FROM_AT(lchip)?
                    p_dsnh_param->l3edit_ptr : p_dsnh_param->inner_l2edit_ptr; /*SRH edit*/
            }
            else if (DRV_FROM_AT(lchip) && (1 == p_dsnh_param->dvp_tbl_valid))
            {
                dsnh.outer_edit_ptr_type = 1;
                dsnh.outer_edit_ptr = p_dsnh_param->l3edit_ptr;
            }

            if (!DRV_FROM_AT(lchip) || (1 != p_dsnh_param->dvp_tbl_valid))
            {
                dsnh.inner_edit_ptr_type = 1;
                dsnh.inner_edit_ptr = DRV_FROM_AT(lchip)?
                    p_dsnh_param->inner_l2edit_ptr : p_dsnh_param->l3edit_ptr;   /*SR tunnel L2edit*/
            }
        }

        dsnh.mtu_check_en = TRUE;
        dsnh.strip_l2_hdr = p_dsnh_param->strip_l2_hdr;
        if (p_dsnh_param->p_vlan_info)
        {
            dsnh.vlan_xlate_mode = 1;       /*humber mode*/
            dsnh.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, &dsnh, p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh4w_assign_vid(lchip, &dsnh, p_dsnh_param->p_vlan_info));
        }
        if (DRV_FROM_AT(lchip))
        {
            dsnh.dvp_tbl_valid = 1;
            if (dsnh.aps_bridge_en)
            {
                dsnh.srv6_aps_en = 1;
            }
        }
        dsnh.is_encap = 1;
        break;

    case SYS_NH_PARAM_DSNH_TYPE_TRILL:

        dsnh.payload_operation = SYS_NH_OP_BRIDGE_VPLS;
        dsnh.svlan_tagged = TRUE;
        dsnh.mtu_check_en = TRUE;
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);

        dsnh.outer_edit_location = 1;
        dsnh.outer_edit_ptr_type = 0;
        dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;  /*outer L2edit*/

        dsnh.inner_edit_ptr_type = 1;
        dsnh.inner_edit_ptr = p_dsnh_param->l3edit_ptr;  /*L3 edit*/
        if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM))
        {
            /*use spme resource to edit ARP*/
            dsnh.outer_edit_ptr_type = 1;
            dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
            dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)?(1 << 11):(1 << 10));
        }
        break;

    case SYS_NH_PARAM_DSNH_TYPE_IPTUNNEL_FOR_MIRROR:
        dsnh.payload_operation = SYS_NH_OP_MIRROR;
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh, p_dsnh_param->flag);

        dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;

        dsnh.outer_edit_location = 1;
        dsnh.outer_edit_ptr_type = 0;   /*Pipe2: L2edit*/
        dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;

        dsnh.inner_edit_ptr_type = 1;   /*L3edit*/
        dsnh.inner_edit_ptr = p_dsnh_param->l3edit_ptr;
        if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM))
        {
            /*use spme resource to edit ARP*/
            dsnh.outer_edit_ptr_type = 1;
            dsnh.outer_edit_ptr = dsnh.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
            dsnh.outer_edit_ptr |= (DRV_FROM_TMM(lchip)?(1 << 11):(1 << 10));
        }
        break;
case SYS_NH_PARAM_DSNH_TYPE_OF:
        dsnh.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_MISC_FLEX_PLD_BRIDGE))
        {
            dsnh.payload_operation = SYS_NH_OP_BRIDGE;
            dsnh.svlan_tagged = TRUE;
        }
        else
        {
            dsnh.payload_operation = SYS_NH_OP_NONE;
        }
        dsnh.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh.share_type = SYS_NH_SHARE_TYPE_L23EDIT;

        if (p_dsnh_param->lspedit_ptr)
        {
            dsnh.outer_edit_location = 0;
            dsnh.outer_edit_ptr_type = 1; /*L3edit*/
            dsnh.outer_edit_ptr = p_dsnh_param->lspedit_ptr;
        }
        else
        {
            dsnh.outer_edit_location = p_dsnh_param->outer_edit_location;
            dsnh.outer_edit_ptr_type = 0; /*L2edit*/
            dsnh.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
        }

        dsnh.inner_edit_ptr_type = 1;/*L3edit*/
        dsnh.inner_edit_ptr = p_dsnh_param->l3edit_ptr;
        if (DRV_FROM_AT(lchip))
        {
            dsnh.dvp_tbl_valid = 1;
        }
        break;

    default:
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] DsNexthop table type is invalid \n");
			return CTC_E_INVALID_CONFIG;

    }

    dsnh.logic_dest_port = p_dsnh_param->logic_port;
    dsnh.logic_port_check = p_dsnh_param->logic_port_check;
    if (dsnh.logic_dest_port)
    {
        dsnh.dvp_tbl_valid = 1;
    }
    if (p_dsnh_param->p_vlan_info && (0xfffe == p_dsnh_param->p_vlan_info->user_vlanptr))
    {
        dsnh.destVlanPtrDeriveMode = 1;
        dsnh.dest_vlan_ptr = 0;
    }
    if (p_dsnh_param->pl_op)
    {
        dsnh.payload_operation = p_dsnh_param->pl_op;
    }

    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip,
                                                       SYS_NH_ENTRY_TYPE_NEXTHOP_4W, p_dsnh_param->dsnh_offset, &dsnh));

    return CTC_E_NONE;
}

int32
sys_usw_nh_write_entry_dsnh8w(uint8 lchip, sys_nh_param_dsnh_t* p_dsnh_param)
{
    sys_nexthop_t dsnh_8w;
    uint32 op_bridge = 0;
    uint32 op_route_no_ttl = 0;
    uint8 xgpon_en = 0;
    uint8  bpe_pe_mode = 0;

    sal_memset(&dsnh_8w, 0, sizeof(dsnh_8w));

    if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_L2EDIT_AS_APS_GROUP))
    {
        dsnh_8w.aps_bridge_en = 1;
    }

    dsnh_8w.stats_ptr  = p_dsnh_param->stats_ptr;
    dsnh_8w.dvp_tbl_valid = p_dsnh_param->dvp_tbl_valid;
    if (!p_dsnh_param->esi_id_index_valid)
    {
        dsnh_8w.cid_valid = p_dsnh_param->cid?1:0;
    }
    else
    {
        dsnh_8w.cid_valid = 0;
        dsnh_8w.esi_id_index_en = 1;
    }
    dsnh_8w.cid       = p_dsnh_param->cid;

    bpe_pe_mode = (g_usw_nh_master[lchip]->bpe_en&0x1)?1:0;
    if (bpe_pe_mode && p_dsnh_param->stats_ptr)
    {
        /*bpe ecid enable, cannot support nh stats*/
        return CTC_E_INVALID_CONFIG;
    }

    switch (p_dsnh_param->dsnh_type)
    {
    case SYS_NH_PARAM_DSNH_TYPE_IPUC:
        dsnh_8w.share_type = 0;
        dsnh_8w.mtu_check_en = !(p_dsnh_param->mtu_no_chk);

        /*IPUC only use ROUTE_COMPACT in current GB SDK*/
           SYS_USW_NH_DSNH_BUILD_FLAG(dsnh_8w, p_dsnh_param->flag);
           if(CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL))
           {
               dsnh_8w.payload_operation = SYS_NH_OP_ROUTE_NOTTL;
           }
           else
           {
               dsnh_8w.payload_operation = SYS_NH_OP_ROUTE;
           }

           dsnh_8w.outer_edit_valid    = 1;
           dsnh_8w.outer_edit_ptr_type = 0;/*L2edit*/
           dsnh_8w.logic_dest_port = p_dsnh_param->logic_port;
           if (p_dsnh_param->l2edit_ptr)
           {
               dsnh_8w.outer_edit_location = 1;/*Pipe1*/
               dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
               if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM))
               {
                   /*use spme resource to edit ARP*/
                   dsnh_8w.outer_edit_ptr_type = 1;
                   dsnh_8w.outer_edit_ptr = dsnh_8w.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                   dsnh_8w.outer_edit_ptr |= (DRV_FROM_TMM(lchip)? (1 << 11) : (1 << 10));
               }
           }
           else if (p_dsnh_param->inner_l2edit_ptr)
           {
               dsnh_8w.outer_edit_location = 0;/*Pipe0*/
               dsnh_8w.outer_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
           }

           /*for phy if vlan, no use any more*/
        dsnh_8w.dest_vlan_ptr = p_dsnh_param->dest_vlan_ptr;
        dsnh_8w.strip_l2_hdr = 1;
        dsnh_8w.use_packet_ttl = p_dsnh_param->use_ttl_from_pkt;
        break;

    case SYS_NH_PARAM_DSNH_TYPE_IPMC:
        dsnh_8w.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        dsnh_8w.svlan_tagged = 1;
        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh_8w.payload_operation = SYS_NH_OP_ROUTE;
        dsnh_8w.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
        if(p_dsnh_param->inner_l2edit_ptr)
        {
            dsnh_8w.inner_edit_ptr_type = 0; /* L2Edit(1)*/
            dsnh_8w.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
        }
        if(p_dsnh_param->l2edit_ptr)
        {
            dsnh_8w.outer_edit_ptr_type = 0;/*L2edit*/
            dsnh_8w.outer_edit_location = 0;/*Pipe0*/
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
        }
        dsnh_8w.logic_dest_port     = p_dsnh_param->logic_port;
        dsnh_8w.logic_port_check    = p_dsnh_param->logic_port_check;
        if (p_dsnh_param->p_vlan_info)  /* vlan edit from nexthop not from L2edit */
        {
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, (sys_nexthop_t*)(&dsnh_8w), p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh8w_assign_vid(lchip, &dsnh_8w, p_dsnh_param->p_vlan_info));
            if (p_dsnh_param->tag_disable)
            {
                dsnh_8w.cvlan_tag_disable = 1;
                dsnh_8w.svlan_tag_disable = 1;
            }
        }
        break;
    case SYS_NH_PARAM_DSNH_TYPE_BRGUC:
        SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh_8w);
        dsnh_8w.payload_operation = SYS_NH_OP_BRIDGE;
        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        sys_usw_global_get_xgpon_en(lchip, &xgpon_en);
        if (xgpon_en)
        {
            if (p_dsnh_param->p_vlan_info && CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_SERVICE_QUEUE_FLAG)
                && CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF))
            {
                dsnh_8w.vlan_xlate_mode = 0;
                CTC_UNSET_FLAG(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF);
            }
            else
            {
                dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
            }
            if (p_dsnh_param->l3edit_ptr && DRV_IS_DUET2(lchip))
            {
                dsnh_8w.inner_edit_ptr_type = 1;
                dsnh_8w.inner_edit_ptr = g_usw_nh_master[lchip]->mpls_edit_offset + p_dsnh_param->l3edit_ptr -1;
            }
        }
        else
        {
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
        }

        dsnh_8w.logic_dest_port     = p_dsnh_param->logic_port;
        dsnh_8w.logic_port_check    = p_dsnh_param->logic_port_check;
        dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;

        if (p_dsnh_param->p_vlan_info && CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_STATS_EN))
        {
            CTC_ERROR_RETURN(sys_usw_flow_stats_get_statsptr(lchip, p_dsnh_param->p_vlan_info->stats_id, &(dsnh_8w.stats_ptr)));
            if (bpe_pe_mode && dsnh_8w.stats_ptr)
            {
                /*bpe ecid enable, cannot support nh stats*/
                return CTC_E_INVALID_CONFIG;
            }
        }

        if(p_dsnh_param->logic_port_check)
        {
            dsnh_8w.logic_dest_port     = p_dsnh_param->logic_port;
            dsnh_8w.logic_port_check    = 1;
        }

        if (p_dsnh_param->p_vlan_info)
        {
            dsnh_8w.share_type = SYS_NH_SHARE_TYPE_VLANTAG;

            if (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF) || p_dsnh_param->is_leaf)
            {
                dsnh_8w.is_leaf = 1;
            }
            if (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_PASS_THROUGH))
            {
                dsnh_8w.payload_operation = SYS_NH_OP_BRIDGE_INNER;
            }

            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, (sys_nexthop_t*)(&dsnh_8w), p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh8w_assign_vid(lchip, &dsnh_8w, p_dsnh_param->p_vlan_info));
        }

        break;

    case SYS_NH_PARAM_DSNH_TYPE_MPLS_PUSH_OP_NONE : /*Swap  label on LSR /Pop label and do   label  Swap on LER*/
        dsnh_8w.payload_operation = SYS_NH_OP_NONE;
        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh_8w, p_dsnh_param->flag);

        if (p_dsnh_param->lspedit_ptr || (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_L2EDIT_AS_APS_GROUP)))
        {
            dsnh_8w.outer_edit_location = (p_dsnh_param->spme_mode)?1:0;
            dsnh_8w.outer_edit_ptr_type = 1;/*Pipe0: L3edit*/
            dsnh_8w.outer_edit_ptr = p_dsnh_param->lspedit_ptr;
        }
        else
        {
            dsnh_8w.outer_edit_location = p_dsnh_param->loop_edit?0:1;
            dsnh_8w.outer_edit_ptr_type = 0;/*Pipe0: L2edit*/
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
            if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && !p_dsnh_param->loop_edit)
            {
                /*use spme resource to edit ARP*/
                dsnh_8w.outer_edit_ptr_type = 1;
                dsnh_8w.outer_edit_ptr = dsnh_8w.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                dsnh_8w.outer_edit_ptr |= (DRV_FROM_TMM(lchip)?(1 << 11):(1 << 10));
            }
        }

        dsnh_8w.logic_dest_port    = p_dsnh_param->logic_port;
        dsnh_8w.inner_edit_ptr_type = 1;/*L3Edit*/
        dsnh_8w.inner_edit_ptr = p_dsnh_param->l3edit_ptr;

        break;
    case SYS_NH_PARAM_DSNH_TYPE_MPLS_PUSH_OP_ROUTE: /* (L3VPN/FTN)*/
        dsnh_8w.payload_operation = SYS_NH_OP_ROUTE;
        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh_8w, p_dsnh_param->flag);

        dsnh_8w.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
        dsnh_8w.is_encap = 1;
        if (dsnh_8w.aps_bridge_en)
        {
            dsnh_8w.outer_edit_location = 0;
            dsnh_8w.outer_edit_ptr_type = 1;
            dsnh_8w.outer_edit_ptr = p_dsnh_param->lspedit_ptr;/*aps group*/
        }
        else
        {
            if (p_dsnh_param->spme_mode)
            {
                dsnh_8w.outer_edit_location = 1;
                dsnh_8w.outer_edit_ptr_type = 1;
                dsnh_8w.outer_edit_ptr = p_dsnh_param->lspedit_ptr;/*Pipe0: L3edit*/
            }
            else
            {
                if(p_dsnh_param->lspedit_ptr) /*LSP+ARP*/
                {
                    dsnh_8w.outer_edit_location = 0;
                    dsnh_8w.outer_edit_ptr_type = 1;
                    dsnh_8w.outer_edit_ptr = p_dsnh_param->lspedit_ptr;/*Pipe0: L3edit*/
                }
                else /*ARP or loop*/
                {
                    dsnh_8w.outer_edit_location = p_dsnh_param->loop_edit?0:1; /*for loop, using pipe0*/
                    dsnh_8w.outer_edit_ptr_type = 0;
                    dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;/*Pipe3: l2edti*/
                    if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && !p_dsnh_param->loop_edit)
                    {
                        /*use spme resource to edit ARP*/
                        dsnh_8w.outer_edit_ptr_type = 1;
                        dsnh_8w.outer_edit_ptr = dsnh_8w.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                        dsnh_8w.outer_edit_ptr |= (DRV_FROM_TMM(lchip)? (1 << 11) : (1 << 10));
                    }
                }
            }

        }

        dsnh_8w.inner_edit_ptr_type = 1;/* L3Edit*/
        dsnh_8w.inner_edit_ptr = p_dsnh_param->l3edit_ptr;

        dsnh_8w.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        dsnh_8w.strip_l2_hdr = 1;
        dsnh_8w.logic_dest_port     = p_dsnh_param->logic_port;
        break;
    case SYS_NH_PARAM_DSNH_TYPE_MPLS_PUSH_OP_L2VPN:
        if (p_dsnh_param->hvpls)
        {
            op_bridge = SYS_NH_OP_BRIDGE_INNER;
        }
        else
        {
            op_bridge = SYS_NH_OP_BRIDGE_VPLS;
        }

        if (p_dsnh_param->spme_mode)
        {
            op_bridge = SYS_NH_OP_NONE;
        }

        if (p_dsnh_param->p_vlan_info)
        {
            if (CTC_FLAG_ISSET(p_dsnh_param->p_vlan_info->flag, CTC_VLAN_NH_ETREE_LEAF))
            {
                dsnh_8w.is_leaf = 1;
            }

            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
            dsnh_8w.payload_operation = op_bridge;
            dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
            dsnh_8w.mtu_check_en = !(p_dsnh_param->mtu_no_chk);

            dsnh_8w.share_type = SYS_NH_SHARE_TYPE_VLANTAG;

            if (p_dsnh_param->spme_mode)
            {
                dsnh_8w.outer_edit_location = 0;
                dsnh_8w.outer_edit_ptr_type = 1;
                dsnh_8w.outer_edit_ptr = p_dsnh_param->l3edit_ptr;

                dsnh_8w.inner_edit_ptr_type = 0;
                dsnh_8w.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
            }
            else
            {
                if(p_dsnh_param->lspedit_ptr || (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_L2EDIT_AS_APS_GROUP)))
                {
                    dsnh_8w.outer_edit_location = 0;
                    dsnh_8w.outer_edit_ptr_type = 1;
                    dsnh_8w.outer_edit_ptr = p_dsnh_param->lspedit_ptr; /*Pipe0: L3edit*/
                }
                else
                {
                    dsnh_8w.outer_edit_location = p_dsnh_param->loop_edit?0:1;
                    dsnh_8w.outer_edit_ptr_type = 0;
                    dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr; /*Pipe0: L2edit*/
                    if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && !p_dsnh_param->loop_edit)
                    {
                        /*use spme resource to edit ARP*/
                        dsnh_8w.outer_edit_ptr_type = 1;
                        dsnh_8w.outer_edit_ptr = dsnh_8w.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                        dsnh_8w.outer_edit_ptr |= (DRV_FROM_TMM(lchip)? (1 << 11) : (1 << 10));
                    }
                }

                if (p_dsnh_param->loop_edit && p_dsnh_param->inner_l2edit_ptr)
                {
                    /*do inner l2 edit*/
                    dsnh_8w.inner_edit_ptr_type = 0; /* L2Edit(1)*/
                    dsnh_8w.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
                }else
                {
                    dsnh_8w.inner_edit_ptr_type = 1;
                    dsnh_8w.inner_edit_ptr = p_dsnh_param->l3edit_ptr;
                }

                CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, (&dsnh_8w) /*Have same structure*/,
                                                                       p_dsnh_param->p_vlan_info));
                CTC_ERROR_RETURN(sys_usw_nh_dsnh8w_assign_vid(lchip, &dsnh_8w, p_dsnh_param->p_vlan_info));
            }

            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dsnh8w.dest_vlanptr = %d, payloadOp = %d \n",
                           dsnh_8w.dest_vlan_ptr, dsnh_8w.payload_operation);

        }
        else
        {
            CTC_ERROR_RETURN(CTC_E_INVALID_PARAM);
        }

        dsnh_8w.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        dsnh_8w.cw_index = p_dsnh_param->cw_index;
        dsnh_8w.logic_dest_port     = p_dsnh_param->logic_port;
        dsnh_8w.is_encap = 1;

        break;

    case SYS_NH_PARAM_DSNH_TYPE_IPTUNNEL:
        op_bridge = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_BRIDGE)) ? 1: 0;
        op_route_no_ttl = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL)) ? 1:0;

        if (op_bridge)
        {
            dsnh_8w.payload_operation = p_dsnh_param->hvpls?SYS_NH_OP_BRIDGE_INNER: SYS_NH_OP_BRIDGE_VPLS;
        }
        else
        {
            if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_NONE))
            {
                dsnh_8w.payload_operation = SYS_NH_OP_NONE;
            }
            else
            {
                dsnh_8w.payload_operation = op_route_no_ttl? SYS_NH_OP_ROUTE_NOTTL : SYS_NH_OP_ROUTE;
            }
        }

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_STRIP_VLAN))
        {
            dsnh_8w.svlan_tagged = FALSE;
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
        }
        else
        {
           dsnh_8w.svlan_tagged = TRUE;
           dsnh_8w.svlan_tag_disable = (p_dsnh_param->p_vlan_info || p_dsnh_param->svlan_tpid_en) ? FALSE : TRUE;
        }
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_STRIP_CVLAN))
        {
            dsnh_8w.cvlan_strip = 1;
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
        }
        dsnh_8w.bridge_inner = 1; /*From TM.MX, bridge inner from DsNextHop and default do bridge inner*/
        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh_8w.mtu_check_en = FALSE;
        dsnh_8w.is_encap = 1;

        dsnh_8w.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_NAT) && DRV_FROM_AT(lchip))
        {
            dsnh_8w.outer_edit_location = 0;
            dsnh_8w.outer_edit_ptr_type = 1;
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l3edit_ptr;  /*Pipe0 L3edit*/
            dsnh_8w.inner_edit_ptr_type = 0;
            dsnh_8w.inner_edit_ptr = 0;
        }
        else if (p_dsnh_param->only_l3edit)
        {
            dsnh_8w.outer_edit_ptr_type = 1;
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l3edit_ptr;  /*Pipe0 L3edit*/
        }
        else if (p_dsnh_param->inner_l2edit_ptr)
        { /*outer L2Edit*/
           dsnh_8w.outer_edit_location = 0;
           dsnh_8w.outer_edit_ptr_type = 1;
           dsnh_8w.outer_edit_ptr = p_dsnh_param->l3edit_ptr;  /*Pipe0 L3edit*/

           dsnh_8w.inner_edit_ptr_type = 0;
           dsnh_8w.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;  /*inner L2edit*/

        }
        else
        {
            dsnh_8w.outer_edit_location = (p_dsnh_param->loop_edit || p_dsnh_param->over_l2_edit)?0:1;
            dsnh_8w.outer_edit_ptr_type = 0;
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;  /*outer L2edit*/

            dsnh_8w.inner_edit_ptr_type = 1;
            dsnh_8w.inner_edit_ptr = p_dsnh_param->l3edit_ptr;  /*L3 edit*/
            if (p_dsnh_param->l2edit_ptr >= MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) && dsnh_8w.outer_edit_location)
            {
                /*use spme resource to edit ARP*/
                dsnh_8w.outer_edit_ptr_type = 1;
                dsnh_8w.outer_edit_ptr = dsnh_8w.outer_edit_ptr - MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM);
                dsnh_8w.outer_edit_ptr |= (DRV_FROM_TMM(lchip)? (1 << 11) : (1 << 10));
            }
        }

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ERSPAN_EN))
        {
            dsnh_8w.fid_valid          = 0;
            dsnh_8w.fid                = p_dsnh_param->span_id;
            dsnh_8w.span_en            = 1;
            dsnh_8w.share_type = SYS_NH_SHARE_TYPE_VLANTAG;  /*here using SYS_NH_SHARE_TYPE_VLANTAG just for stats ptr in dsnexthop8w*/
            dsnh_8w.payload_operation = SYS_NH_OP_MIRROR;

			if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ERSPAN_KEEP_IGS_TS))
            {
                dsnh_8w.keep_igs_ts = 1;
            }

        }
        else
        {
            dsnh_8w.fid_valid          = (0 == p_dsnh_param->fid)? 0 : 1;
            dsnh_8w.fid                = p_dsnh_param->fid;
        }

        if (p_dsnh_param->p_vlan_info)  /*misc over l2 edit with inner vlan edit*/
        {
            dsnh_8w.payload_operation = SYS_NH_OP_BRIDGE_INNER;
            dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
            dsnh_8w.share_type = SYS_NH_SHARE_TYPE_VLANTAG;

            SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh_8w);
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, (sys_nexthop_t*)(&dsnh_8w), p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh8w_assign_vid(lchip, &dsnh_8w, p_dsnh_param->p_vlan_info));
        }

        dsnh_8w.is_vxlan_route_op  = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_STRIP_INNER)) ?
            0 : 1;
        dsnh_8w.logic_port_check   = p_dsnh_param->logic_port_check;
        dsnh_8w.logic_dest_port    = p_dsnh_param->logic_port;

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_UDF_EDIT_EN))
        {
            dsnh_8w.is_vxlan_route_op  = 1;
            dsnh_8w.is_wlan_encap  = 1;
            sal_memcpy(&dsnh_8w.mac_da[0], &p_dsnh_param->macDa[0], sizeof(mac_addr_t));
            dsnh_8w.rid = p_dsnh_param->rid;
            dsnh_8w.wlan_mc_en = p_dsnh_param->wlan_mc_en;
        }
        dsnh_8w.strip_l2_hdr = p_dsnh_param->strip_l2_hdr;
        dsnh_8w.use_packet_ttl = p_dsnh_param->use_ttl_from_pkt;

        if(p_dsnh_param->svlan_tpid_en)
        {
            dsnh_8w.svlan_tpid_en = TRUE;
            dsnh_8w.svlan_tpid = p_dsnh_param->svlan_tpid_index;
        }
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dsnh8w.dest_vlanptr = %d, payloadOp = %d \n",
                       dsnh_8w.dest_vlan_ptr, dsnh_8w.payload_operation);

        break;
    case SYS_NH_PARAM_DSNH_TYPE_SRV6:
        dsnh_8w.payload_operation =   (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL))?
                                                                SYS_NH_OP_ROUTE_NOTTL: SYS_NH_OP_ROUTE;
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_BRIDGE))
        {
            dsnh_8w.payload_operation = p_dsnh_param->hvpls?SYS_NH_OP_BRIDGE_INNER: SYS_NH_OP_BRIDGE_VPLS;
        }
        dsnh_8w.svlan_tagged = TRUE;
        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh_8w.is_encap = 1;
        SYS_USW_NH_DSNH_BUILD_FLAG(dsnh_8w, p_dsnh_param->flag);
        dsnh_8w.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
        if (p_dsnh_param->loop_edit)
        {
            dsnh_8w.outer_edit_ptr_type = 0;
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr; /*loop edit*/
        }
        else if((0 == p_dsnh_param->inner_l2edit_ptr) && (0 == p_dsnh_param->dvp_tbl_valid))/*BE mode*/
        {
            dsnh_8w.outer_edit_ptr_type = 1;
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l3edit_ptr; /*ipv6 tunnel edit*/
        }
        else
        {
            if (0 == p_dsnh_param->dvp_tbl_valid)
            {
                dsnh_8w.outer_edit_ptr_type = 1;
                dsnh_8w.outer_edit_ptr = DRV_FROM_AT(lchip)?
                    p_dsnh_param->l3edit_ptr : p_dsnh_param->inner_l2edit_ptr;  /*SRH edit*/
            }
            dsnh_8w.inner_edit_ptr_type = 1;
            dsnh_8w.inner_edit_ptr = DRV_FROM_AT(lchip)?
                p_dsnh_param->inner_l2edit_ptr : p_dsnh_param->l3edit_ptr;  /*SR tunnel L3edit*/
        }
        dsnh_8w.mtu_check_en = TRUE;
        dsnh_8w.logic_port_check   = p_dsnh_param->logic_port_check;
        dsnh_8w.logic_dest_port    = p_dsnh_param->logic_port;
        dsnh_8w.strip_l2_hdr = p_dsnh_param->strip_l2_hdr;

        if (p_dsnh_param->p_vlan_info)
        {
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
            dsnh_8w.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
            SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh_8w);
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, (sys_nexthop_t*)(&dsnh_8w), p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh8w_assign_vid(lchip, &dsnh_8w, p_dsnh_param->p_vlan_info));
        }
        if (DRV_FROM_AT(lchip))
        {
            dsnh_8w.dvp_tbl_valid = 1;
            if (dsnh_8w.aps_bridge_en)
            {
                dsnh_8w.srv6_aps_en = 1;
            }
        }

        break;
    case SYS_NH_PARAM_DSNH_TYPE_OVERLAY_VNI:
        dsnh_8w.payload_operation = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL) ?
        SYS_NH_OP_ROUTE_NOTTL : SYS_NH_OP_ROUTE);
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_BRIDGE))
        {
            dsnh_8w.payload_operation = p_dsnh_param->hvpls? SYS_NH_OP_BRIDGE_INNER : SYS_NH_OP_BRIDGE_VPLS;
        }
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_STRIP_VLAN))
        {
            dsnh_8w.svlan_tagged = FALSE;
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
        }
        else
        {
            dsnh_8w.svlan_tagged = TRUE;
        }
        dsnh_8w.svlan_tag_disable = FALSE;
        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_STRIP_CVLAN))
        {
            dsnh_8w.cvlan_strip = 1;
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
        }
        dsnh_8w.bridge_inner = 1; /*From TM.MX, bridge inner from DsNextHop and default do bridge inner*/
        if (p_dsnh_param->p_vlan_info)
        {
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, &dsnh_8w,p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh8w_assign_vid(lchip, &dsnh_8w, p_dsnh_param->p_vlan_info));
            dsnh_8w.vlan_xlate_mode = 0; /*misc mode, scl can do vlan edit*/
            dsnh_8w.dest_vlan_ptr = p_dsnh_param->p_vlan_info->user_vlanptr;
            dsnh_8w.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
        }

        if (p_dsnh_param->inner_l2edit_ptr)
        {
            dsnh_8w.outer_edit_location = 0;
            dsnh_8w.inner_edit_ptr_type = 0;
            dsnh_8w.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;  /*inner L2edit*/
        }
        dsnh_8w.logic_port_check   = p_dsnh_param->logic_port_check;
        dsnh_8w.fid_valid          = (0 == p_dsnh_param->fid)? 0 : 1;
        dsnh_8w.fid                = p_dsnh_param->fid;
        dsnh_8w.mtu_check_en = FALSE;
        dsnh_8w.strip_l2_hdr = p_dsnh_param->strip_l2_hdr;
        dsnh_8w.logic_dest_port    = p_dsnh_param->logic_port;
        break;
    case SYS_NH_PARAM_DSNH_TYPE_XERSPAN:
        dsnh_8w.payload_operation = SYS_NH_OP_MIRROR;
        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh_8w.mtu_check_en = TRUE;
        dsnh_8w.xerpsan_en = TRUE;
        dsnh_8w.share_type = SYS_NH_SHARE_TYPE_SPAN_PACKET;
        dsnh_8w.outer_edit_location = 0;
        dsnh_8w.outer_edit_ptr_type = 0;
        dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;

        dsnh_8w.inner_edit_ptr_type = 1;
        dsnh_8w.inner_edit_ptr = p_dsnh_param->l3edit_ptr;
        dsnh_8w.hash_num = p_dsnh_param->hash_num;

        dsnh_8w.fid_valid          = 0;
        dsnh_8w.fid                = p_dsnh_param->span_id;
        dsnh_8w.span_en            = 1;

        if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ERSPAN_KEEP_IGS_TS))
        {
            dsnh_8w.keep_igs_ts = 1;
        }


        break;

    case SYS_NH_PARAM_DSNH_TYPE_WLANTUNNEL:
        op_bridge = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_IP_TUNNEL_PLD_BRIDGE)) ? 1: 0;
        op_route_no_ttl = (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ROUTE_NOTTL)) ? 1:0;
        dsnh_8w.payload_operation = op_bridge ? SYS_NH_OP_NONE : SYS_NH_OP_ROUTE;
        dsnh_8w.svlan_tagged = p_dsnh_param->stag_en;
        if (op_bridge)
        {
            dsnh_8w.payload_operation = SYS_NH_OP_BRIDGE;
        }
        else
        {
            dsnh_8w.payload_operation = op_route_no_ttl? SYS_NH_OP_ROUTE_NOTTL : SYS_NH_OP_ROUTE;
        }

        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh_8w.mtu_check_en = TRUE;

        dsnh_8w.share_type = SYS_NH_SHARE_TYPE_L23EDIT;

       if (p_dsnh_param->inner_l2edit_ptr)
        { /*outer L2Edit*/
           dsnh_8w.outer_edit_location = 0;
           dsnh_8w.outer_edit_ptr_type = 1;
           dsnh_8w.outer_edit_ptr = p_dsnh_param->l3edit_ptr;  /*Pipe0 L3edit*/

           dsnh_8w.inner_edit_ptr_type = 0;
           dsnh_8w.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;  /*inner L2edit*/

        }
        else
        {
            dsnh_8w.inner_edit_ptr_type = 1;
            dsnh_8w.inner_edit_ptr = p_dsnh_param->l3edit_ptr;  /*L3 edit*/

        }

        dsnh_8w.logic_port_check   = p_dsnh_param->logic_port_check;
        dsnh_8w.logic_dest_port    = p_dsnh_param->logic_port;
        dsnh_8w.is_wlan_encap = 1;
        dsnh_8w.wlan_tunnel_type = p_dsnh_param->wlan_tunnel_type;
        dsnh_8w.is_dot11 = p_dsnh_param->is_dot11;
        dsnh_8w.wlan_mc_en = p_dsnh_param->wlan_mc_en;
        dsnh_8w.rid = p_dsnh_param->rid;
        sal_memcpy(dsnh_8w.mac_da, p_dsnh_param->macDa, sizeof(mac_addr_t));

        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "dsnh8w.dest_vlanptr = %d, payloadOp = %d \n",
                       dsnh_8w.dest_vlan_ptr, dsnh_8w.payload_operation);

        break;

case SYS_NH_PARAM_DSNH_TYPE_OF:
        dsnh_8w.mtu_check_en = !(p_dsnh_param->mtu_no_chk);
        if (p_dsnh_param->pl_op)
        {
            dsnh_8w.payload_operation = p_dsnh_param->pl_op;
        }
        else if (CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_MISC_FLEX_PLD_BRIDGE) ||
            CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ERSPAN_EN))
        {
            dsnh_8w.payload_operation = CTC_FLAG_ISSET(p_dsnh_param->flag, SYS_NH_PARAM_FLAG_ERSPAN_EN) ? SYS_NH_OP_BRIDGE_INNER:SYS_NH_OP_BRIDGE;
            dsnh_8w.svlan_tagged = 1;
        }
        else
        {
            dsnh_8w.payload_operation = SYS_NH_OP_NONE;
        }

        dsnh_8w.dest_vlan_ptr  = p_dsnh_param->dest_vlan_ptr;
        dsnh_8w.share_type = SYS_NH_SHARE_TYPE_L23EDIT;
        dsnh_8w.logic_dest_port    = p_dsnh_param->logic_port;

        if (p_dsnh_param->lspedit_ptr)
        {
            dsnh_8w.outer_edit_location = 0;
            dsnh_8w.outer_edit_ptr_type = 1; /*l3edit*/
            dsnh_8w.outer_edit_ptr = p_dsnh_param->lspedit_ptr;
        }
        else
        {
            dsnh_8w.outer_edit_location = p_dsnh_param->outer_edit_location;
            dsnh_8w.outer_edit_ptr_type = 0; /*l2edit*/
            dsnh_8w.outer_edit_ptr = p_dsnh_param->l2edit_ptr;
        }
        if (p_dsnh_param->inner_l2edit_ptr)
        {
            dsnh_8w.inner_edit_ptr_type = 0;/*L2edit*/
            dsnh_8w.inner_edit_ptr = p_dsnh_param->inner_l2edit_ptr;
        }
        else
        {
            dsnh_8w.inner_edit_ptr_type = 1;/*L3edit*/
            dsnh_8w.inner_edit_ptr = p_dsnh_param->l3edit_ptr;
        }

        if (p_dsnh_param->span_id != 0)
        {
            dsnh_8w.fid_valid          = 0;
            dsnh_8w.fid                = p_dsnh_param->span_id;
            dsnh_8w.span_en            = 1;
        }

        if (p_dsnh_param->p_vlan_info)  /* vlan edit from nexthop not from L2edit */
        {
            dsnh_8w.vlan_xlate_mode = 1;       /*humber mode*/
            CTC_ERROR_RETURN(sys_usw_nh_dsnh_build_vlan_info(lchip, (sys_nexthop_t*)(&dsnh_8w), p_dsnh_param->p_vlan_info));
            CTC_ERROR_RETURN(sys_usw_nh_dsnh8w_assign_vid(lchip, &dsnh_8w, p_dsnh_param->p_vlan_info));
        }
        if (p_dsnh_param->tag_disable)
        {
            dsnh_8w.cvlan_tag_disable = 1;
            dsnh_8w.svlan_tag_disable = 1;
        }
        break;

    default:
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] DsNexthop table type is invalid \n");
			return CTC_E_INVALID_CONFIG;

    }

    if (dsnh_8w.logic_dest_port)
    {
        dsnh_8w.dvp_tbl_valid = 1;
    }
    dsnh_8w.is_nexthop8_w = TRUE;
    if (p_dsnh_param->p_vlan_info && (0xfffe == p_dsnh_param->p_vlan_info->user_vlanptr))
    {
        dsnh_8w.destVlanPtrDeriveMode = 1;
        dsnh_8w.dest_vlan_ptr = 0;
    }
    if (p_dsnh_param->pl_op)
    {
        dsnh_8w.payload_operation = p_dsnh_param->pl_op;
    }

    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip,
                                                       SYS_NH_ENTRY_TYPE_NEXTHOP_8W, p_dsnh_param->dsnh_offset, &dsnh_8w));

    return CTC_E_NONE;
}

/**
 @brief This function is used to get dsfwd info
 */
int32
sys_usw_nh_get_entry_dsfwd(uint8 lchip, uint32 dsfwd_offset, void* p_dsfwd, uint8 is_dsfwd1)
{
    DsFwd_m dsfwd;
    DsFwdHalf_m dsfwd_half;

    sys_fwd_t* p_tmp_fwd = 0;
    uint8 is_half = 0;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    p_tmp_fwd = (sys_fwd_t*)p_dsfwd;

    CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, is_dsfwd1? SYS_NH_ENTRY_TYPE_FWD1 : SYS_NH_ENTRY_TYPE_FWD,
                                                      dsfwd_offset, &dsfwd));

    is_half = GetDsFwd(V, isHalf_f, &dsfwd) || (dsfwd_offset&0x1);

    if (0 == is_half)
    {
        p_tmp_fwd->dest_map = GetDsFwd(V, destMap_f, &dsfwd);
    }
    else
    {
        if (dsfwd_offset % 2 == 0)
        {
            GetDsFwdDualHalf(A, g_0_dsFwdHalf_f,   &dsfwd,   &dsfwd_half);
        }
        else
        {
            GetDsFwdDualHalf(A, g_1_dsFwdHalf_f,   &dsfwd,   &dsfwd_half);
        }

        p_tmp_fwd->dest_map = GetDsFwdHalf(V, destMap_f, &dsfwd_half);
        p_tmp_fwd->nexthop_ext = GetDsFwdHalf(V, nextHopExt_f, &dsfwd_half);
    }

    return CTC_E_NONE;

}

/**
 @brief This function is used to build and write dsfwd table
 */
int32
sys_usw_nh_write_entry_dsfwd(uint8 lchip, sys_nh_param_dsfwd_t* p_dsfwd_param)
{

    sys_fwd_t sys_fwd;
    uint8 gchip = 0;
    uint16 sub_queue_id = 0;
    int32 ret = 0;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    sal_memset(&sys_fwd, 0, sizeof(sys_fwd));
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "\n\
        lchip = %d, \n\
        dsfwd_offset = 0x%x, \n\
        dest_chip_id = %d, \n\
        dest_id = 0x%x, \n\
        dropPkt = %d, \n\
        dsnh_offset = 0x%x, \n\
        is_mcast = %d\n",
                   lchip,
                   p_dsfwd_param->dsfwd_offset,
                   p_dsfwd_param->dest_chipid,
                   p_dsfwd_param->dest_id,
                   p_dsfwd_param->drop_pkt,
                   p_dsfwd_param->dsnh_offset,
                   p_dsfwd_param->is_mcast);

    if (p_dsfwd_param->dsnh_offset > 0x3FFFF)
    {
        return CTC_E_INVALID_PARAM;
    }

    sys_fwd.aps_bridge_en = (p_dsfwd_param->aps_type == CTC_APS_BRIDGE);
    sys_fwd.force_back_en = p_dsfwd_param->is_reflective;
    sys_fwd.bypass_igs_edit = (p_dsfwd_param->is_egress_edit)?TRUE:FALSE;
    sys_fwd.nexthop_ptr = (p_dsfwd_param->dsnh_offset & 0x3FFFF);
    sys_fwd.nexthop_ext = (p_dsfwd_param->nexthop_ext)?TRUE:FALSE;
    sys_fwd.adjust_len_idx = p_dsfwd_param->adjust_len_idx;
    sys_fwd.cut_through_dis = p_dsfwd_param->cut_through_dis;

    if (p_dsfwd_param->drop_pkt)
    {
        CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
        sys_fwd.nexthop_ptr = 0x3FFFF;
        sys_fwd.dest_map = SYS_ENCODE_DESTMAP(gchip, SYS_RSV_PORT_DROP_ID);
    }

    else
    {
        if (p_dsfwd_param->is_lcpu)
        {
            sys_cpu_reason_dest_info_t dest_info;
            sal_memset(&dest_info, 0, sizeof(dest_info));
            if(CTC_PKT_CPU_REASON_GET_BY_NHPTR(p_dsfwd_param->dsnh_offset) == CTC_PKT_CPU_REASON_ARP_MISS)
            {
                CTC_ERROR_RETURN(_sys_usw_cpu_reason_get_info(lchip, CTC_PKT_CPU_REASON_ARP_MISS, &dest_info));
                sys_fwd.dest_map = SYS_ENCODE_EXCP_DESTMAP_GCHIP(p_dsfwd_param->dest_chipid, dest_info.dest_map);
            }
            else
            {
                ret = sys_usw_get_sub_queue_id_by_cpu_reason(lchip, CTC_PKT_CPU_REASON_FWD_CPU, &sub_queue_id);
                if (ret == CTC_E_NONE)
                {
                    CTC_ERROR_RETURN(_sys_usw_cpu_reason_get_info(lchip, CTC_PKT_CPU_REASON_FWD_CPU, &dest_info));
                     sys_fwd.dest_map = SYS_ENCODE_EXCP_DESTMAP_GCHIP(p_dsfwd_param->dest_chipid, dest_info.dest_map);
                }
                else
                {
                     sys_fwd.dest_map = SYS_ENCODE_EXCP_DESTMAP(p_dsfwd_param->dest_chipid, MCHIP_CAP(SYS_CAP_PKT_CPU_QDEST_BY_DMA));
                }
            }
            /*default to CPU by CPU,modify destination by QOS API*/
        }
        else if (p_dsfwd_param->is_mcast)
        {
            if (p_dsfwd_param->use_destmap_profile)
            {
                sys_fwd.dest_map = SYS_ENCODE_ARP_DESTMAP(p_dsfwd_param->dest_id);
            }
            else
            {
                sys_fwd.dest_map = SYS_ENCODE_MCAST_IPE_DESTMAP(p_dsfwd_param->dest_id);
            }

            if (p_dsfwd_param->stats_ptr)
            {
                sys_fwd.nexthop_ptr = p_dsfwd_param->stats_ptr ;
            }
        }
        else
        {
            if (p_dsfwd_param->use_destmap_profile)
            {
                sys_fwd.dest_map = SYS_ENCODE_ARP_DESTMAP(p_dsfwd_param->dest_id);
            }
            else if (p_dsfwd_param->aps_type == CTC_APS_DISABLE && (p_dsfwd_param->dest_chipid != 0x1F)
                && p_dsfwd_param->is_cpu)
            {
                sys_cpu_reason_dest_info_t dest_info;
                sal_memset(&dest_info, 0, sizeof(dest_info));
                CTC_ERROR_RETURN(_sys_usw_cpu_reason_get_info(lchip, CTC_PKT_CPU_REASON_FWD_CPU, &dest_info));
                sys_fwd.dest_map = SYS_ENCODE_EXCP_DESTMAP_GCHIP(p_dsfwd_param->dest_chipid, dest_info.dest_map);
                sys_fwd.nexthop_ptr = CTC_PKT_CPU_REASON_BUILD_NHPTR(CTC_PKT_CPU_REASON_FWD_CPU, 0);
            }
            else
            {
                if (p_dsfwd_param->aps_type == CTC_APS_BRIDGE)
                {
                    sys_fwd.dest_map = SYS_ENCODE_APS_DESTMAP(p_dsfwd_param->dest_chipid, p_dsfwd_param->dest_id);
                }
                else
                {
                    sys_fwd.dest_map = SYS_ENCODE_DESTMAP(p_dsfwd_param->dest_chipid, p_dsfwd_param->dest_id);
                }
            }
        }
    }

    if (sys_fwd.force_back_en || p_dsfwd_param->truncate_profile_id || p_dsfwd_param->is_6w)
    {
        sys_fwd.is_6w = 1;
    }

    if (p_dsfwd_param->is_ecmp)
    {
        sys_fwd.ecmp_gid = p_dsfwd_param->dest_id;
        sys_fwd.is_ecmp = 1;
    }

    sys_fwd.offset = p_dsfwd_param->dsfwd_offset;
    sys_fwd.truncate_profile = p_dsfwd_param->truncate_profile_id;
    sys_fwd.cloud_sec_en = p_dsfwd_param->cloud_sec_en;
    sys_fwd.logic_port = p_dsfwd_param->logic_port;
    sys_fwd.logic_port_ext = p_dsfwd_param->logic_port_ext;
    sys_fwd.is_dsfwd1 = DRV_FROM_AT(lchip)? p_dsfwd_param->is_dsfwd1 : 0;
    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip,
        sys_fwd.is_dsfwd1? SYS_NH_ENTRY_TYPE_FWD1 : SYS_NH_ENTRY_TYPE_FWD, p_dsfwd_param->dsfwd_offset, &sys_fwd));


    return CTC_E_NONE;
}

int32
sys_usw_nh_update_entry_dsfwd(uint8 lchip, sys_nh_update_dsfwd_t* p_update_param)
{

    sys_fwd_t sys_fwd;
    DsFwd_m dsfwd;
    uint32 entry_type  = p_update_param->is_dsfwd1? SYS_NH_ENTRY_TYPE_FWD1 : SYS_NH_ENTRY_TYPE_FWD;
    uint32 *offset = p_update_param->is_dsfwd1 ? &p_update_param->dsfwd1_offset : &p_update_param->dsfwd_offset;
    uint8 is_create = 0;

    sal_memset(&sys_fwd, 0, sizeof(sys_fwd));

    if ((*offset) == 0 && p_update_param->del)
    {
        return CTC_E_NONE;
    }

    if ((*offset) == 0 && !p_update_param->del)
    {
        is_create = 1;
        CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, entry_type, 1, offset));
    }
    else if(p_update_param->del)
    {
        CTC_ERROR_RETURN(sys_usw_nh_offset_free(lchip, entry_type, 1, *offset));
    }
    sys_fwd.nexthop_ptr = (p_update_param->dsnh_offset & 0x3FFFF);
    sys_fwd.nexthop_ext = p_update_param->dsnh_8w;
    sys_fwd.dest_map  = p_update_param->dest_map;
    sys_fwd.offset = *offset;
    sys_fwd.bypass_igs_edit = 1;
    sys_fwd.critical_packet = p_update_param->critical_packet;
    sys_fwd.is_6w = 1;
    sys_fwd.is_dsfwd1 = p_update_param->is_dsfwd1;

    if ((*offset) && !p_update_param->del && !is_create)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, entry_type, (*offset), &dsfwd));
        sys_fwd.is_6w = GetDsFwd(V, isHalf_f, &dsfwd)?0:sys_fwd.is_6w;
        sys_fwd.truncate_profile = GetDsFwd(V, truncateLenProfId_f, &dsfwd);

    }
    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, entry_type, sys_fwd.offset, &sys_fwd));
    return CTC_E_NONE;

}

int32
_sys_usw_nh_decode_vlan_edit(uint8 lchip, ctc_vlan_egress_edit_info_t* p_vlan_info, void* ds_nh)
{
    if ((GetDsNextHop4W(V, shareType_f, ds_nh)==1) || (!GetDsNextHop4W(V, shareType_f, ds_nh) && GetDsNextHop4W(V, vlanXlateMode_f, ds_nh)))
    {
        p_vlan_info->output_svid = GetDsNextHop4W(V, outputSvlanId_f, ds_nh);
        p_vlan_info->output_cvid = GetDsNextHop4W(V, outputCvlanId_f, ds_nh);
        p_vlan_info->svlan_tpid_index = GetDsNextHop4W(V, svlanTpidEn_f, ds_nh) ? GetDsNextHop4W(V, svlanTpid_f, ds_nh):0;
        p_vlan_info->stag_cos = GetDsNextHop4W(V, u1_g2_stagCos_f, ds_nh);
        p_vlan_info->edit_flag |= GetDsNextHop4W(V, outputSvlanIdValid_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID:0;
        p_vlan_info->edit_flag |= GetDsNextHop4W(V, outputCvlanIdValid_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_OUPUT_CVID_VALID:0;
        p_vlan_info->edit_flag |= GetDsNextHop4W(V, svlanTpidEn_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_OUTPUT_SVLAN_TPID_VALID:0;
        p_vlan_info->edit_flag |= GetDsNextHop4W(V, stagActionUponOuterVlan_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_SVLAN_AWARE:0;
        if (GetDsNextHop4W(V, cvlanTagDisable_f, ds_nh)&&GetDsNextHop4W(V, svlanTagDisable_f, ds_nh)&&
            GetDsNextHop4W(V, taggedMode_f, ds_nh))
        {
            CTC_SET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_VLAN_SWAP_EN);
            p_vlan_info->edit_flag |= GetDsNextHop4W(V, tpidSwap_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_TPID_SWAP_EN:0;
            p_vlan_info->edit_flag |= GetDsNextHop4W(V, cosSwap_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_COS_SWAP_EN:0;
        }

        if (GetDsNextHop4W(V, u1_g2_replaceStagCos_f, ds_nh) && !GetDsNextHop4W(V, u1_g2_deriveStagCos_f, ds_nh))
        {
            CTC_SET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_REPLACE_SVLAN_COS);
        }

        if (GetDsNextHop4W(V, u1_g2_replaceStagCos_f, ds_nh) && GetDsNextHop4W(V, u1_g2_deriveStagCos_f, ds_nh))
        {
            CTC_SET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_MAP_SVLAN_COS);
        }
    }
    else if (GetDsNextHop4W(V, shareType_f, ds_nh)==2)
    {
        p_vlan_info->output_svid = GetDsNextHop4W(V, u1_g4_outputSvlanId_f, ds_nh);
        p_vlan_info->stag_cos = GetDsNextHop4W(V, u1_g4_stagCos_f, ds_nh);
        p_vlan_info->edit_flag |= GetDsNextHop4W(V, u1_g4_outputSvlanIdValid_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID:0;
        p_vlan_info->edit_flag |= GetDsNextHop4W(V, u1_g4_svlanTpidEn_f, ds_nh)?CTC_VLAN_EGRESS_EDIT_OUTPUT_SVLAN_TPID_VALID:0;
        if (GetDsNextHop4W(V, u1_g4_replaceStagCos_f, ds_nh) && !GetDsNextHop4W(V, u1_g4_deriveStagCos_f, ds_nh))
        {
            CTC_SET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_REPLACE_SVLAN_COS);
        }

        if (GetDsNextHop4W(V, u1_g4_replaceStagCos_f, ds_nh) && GetDsNextHop4W(V, u1_g4_deriveStagCos_f, ds_nh))
        {
            CTC_SET_FLAG(p_vlan_info->edit_flag, CTC_VLAN_EGRESS_EDIT_MAP_SVLAN_COS);
        }
    }

    /*mapping flag*/
    p_vlan_info->flag |= GetDsNextHop4W(V, isLeaf_f, ds_nh)?CTC_VLAN_NH_ETREE_LEAF:0;
    p_vlan_info->flag |= (GetDsNextHop4W(V, payloadOperation_f, ds_nh)==SYS_NH_OP_BRIDGE_VPLS)?CTC_VLAN_NH_HORIZON_SPLIT_EN:0;
    return CTC_E_NONE;
}

int32
_sys_usw_nh_decode_dsmpls(uint8 lchip, void* p_dsmpls, ctc_mpls_nh_label_param_t* push_label)
{
    uint8 ttl_index = 0;
    CTC_PTR_VALID_CHECK(p_dsmpls);
    CTC_PTR_VALID_CHECK(push_label);
    if(DRV_FROM_TMM(lchip))
    {
        push_label->label = GetDsL3EditAddMpls1X(V, label_f, p_dsmpls);
        CTC_SET_FLAG(push_label->lable_flag, CTC_MPLS_NH_LABEL_IS_VALID);
        if (GetDsL3EditAddMpls1X(V, mplsTcRemarkMode_f, p_dsmpls) == 1)
        {
            /*assign*/
            push_label->exp_type = CTC_NH_EXP_SELECT_ASSIGN;
            push_label->exp = GetDsL3EditAddMpls1X(V, uMplsPhb_gRaw_labelTc_f, p_dsmpls);
        }
        else if (GetDsL3EditAddMpls1X(V, mplsTcRemarkMode_f, p_dsmpls) == 3)
        {
            push_label->exp_type = CTC_NH_EXP_SELECT_PACKET;
        }
        else
        {
            push_label->exp_type = CTC_NH_EXP_SELECT_MAP;
            push_label->exp_domain = GetDsL3EditAddMpls1X(V, uMplsPhb_gPtr_mplsTcPhbPtr_f, p_dsmpls);
        }
        if (GetDsL3EditAddMpls1X(V, mcastLabel_f, p_dsmpls))
        {
            CTC_SET_FLAG(push_label->lable_flag, CTC_MPLS_NH_LABEL_IS_MCAST);
        }
        if (GetDsL3EditAddMpls1X(V, mapTtl_f, p_dsmpls))
        {
            CTC_SET_FLAG(push_label->lable_flag, CTC_MPLS_NH_LABEL_MAP_TTL);
        }
        ttl_index = GetDsL3EditAddMpls1X(V, ttlIndex_f, p_dsmpls);
    }
    else
    {
    push_label->label = GetDsL3EditMpls3W(V, label_f, p_dsmpls);
    CTC_SET_FLAG(push_label->lable_flag, CTC_MPLS_NH_LABEL_IS_VALID);
    if (GetDsL3EditMpls3W(V, mplsTcRemarkMode_f, p_dsmpls) == 1)
    {
        /*assign*/
        push_label->exp_type = CTC_NH_EXP_SELECT_ASSIGN;
        push_label->exp = GetDsL3EditMpls3W(V, uMplsPhb_gRaw_labelTc_f, p_dsmpls);
    }
    else if (GetDsL3EditMpls3W(V, mplsTcRemarkMode_f, p_dsmpls) == 3)
    {
        push_label->exp_type = CTC_NH_EXP_SELECT_PACKET;
    }
    else
    {
        push_label->exp_type = CTC_NH_EXP_SELECT_MAP;
        push_label->exp_domain = GetDsL3EditMpls3W(V, uMplsPhb_gPtr_mplsTcPhbPtr_f, p_dsmpls);
    }
    if (GetDsL3EditMpls3W(V, mcastLabel_f, p_dsmpls))
    {
        CTC_SET_FLAG(push_label->lable_flag, CTC_MPLS_NH_LABEL_IS_MCAST);
    }
    if (GetDsL3EditMpls3W(V, mapTtl_f, p_dsmpls))
    {
        CTC_SET_FLAG(push_label->lable_flag, CTC_MPLS_NH_LABEL_MAP_TTL);
    }
    ttl_index = GetDsL3EditMpls3W(V, ttlIndex_f, p_dsmpls);
    }
    CTC_ERROR_RETURN(sys_usw_lkup_ttl_value(lchip, ttl_index, &push_label->ttl));
    return CTC_E_NONE;
}

int32
sys_usw_nh_set_met_aps_en(uint8 lchip, uint32 nhid, uint8 enable)
{
    uint32 dsfwd_offset = 0;
    uint32 met_offset = 0;
    sys_nh_param_dsmet_t dsmet_para;
    sys_nh_info_dsnh_t dsnh_info;
    DsFwd_m dsfwd;
    DsFwdHalf_m dsfwd_half;
    sys_nh_info_com_t* p_nhinfo = NULL;
    sys_nh_info_mpls_t* p_nh_mpls_info = NULL;
    sys_nh_info_srv6_t* p_nh_srv6_info = NULL;
    sys_nh_info_aps_t* p_nh_aps_info = NULL;
    uint32 cmd = 0;
    uint32 group_id = 0;
    uint8  aps_xcon_met = 0;
    uint32 curr_met_offset = 0;

    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM, 1);
    SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_APS, 1);

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, (sys_nh_info_com_t**)&p_nhinfo));
    if (!CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN) ||
        ((p_nhinfo->hdr.nh_entry_type != SYS_NH_TYPE_MPLS)&&
        (p_nhinfo->hdr.nh_entry_type != SYS_NH_TYPE_SRV6)&&
        (p_nhinfo->hdr.nh_entry_type != SYS_NH_TYPE_APS)))
    {
        return CTC_E_NONE;
    }
    if (p_nhinfo->hdr.nh_entry_type == SYS_NH_TYPE_MPLS)
    {
        p_nh_mpls_info = (sys_nh_info_mpls_t*)p_nhinfo;
        group_id = p_nh_mpls_info->gport ;
        aps_xcon_met = p_nh_mpls_info->aps_xcon_met;
        curr_met_offset = p_nh_mpls_info->met_offset;
    }
    else if(p_nhinfo->hdr.nh_entry_type == SYS_NH_TYPE_SRV6)
    {
        p_nh_srv6_info = (sys_nh_info_srv6_t*)p_nhinfo;
        group_id = p_nh_srv6_info->gport ;
        aps_xcon_met = p_nh_srv6_info->aps_xcon_met;
        curr_met_offset = p_nh_srv6_info->met_offset;
    }
    else
    {
        p_nh_aps_info = (sys_nh_info_aps_t*)p_nhinfo;
        group_id = p_nh_aps_info->aps_group_id;
        aps_xcon_met = p_nh_aps_info->aps_xcon_met;
    }

    if((aps_xcon_met && enable) || ((0 == aps_xcon_met) && (0 == enable)))
    {
        return CTC_E_NONE;
    }

    if (p_nhinfo->hdr.nh_entry_type == SYS_NH_TYPE_MPLS || (p_nhinfo->hdr.nh_entry_type == SYS_NH_TYPE_SRV6))
    {
        if (enable)
        {
            CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_MET, 1, &met_offset));
        }
        else if (0 != curr_met_offset)
        {
            sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_MET, 1, curr_met_offset);
            met_offset = 0;
        }
        else
        {
            enable = 1;
        }
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_aps_bind_met( lchip, group_id, &met_offset));
    }

    if (enable)
    {
        sal_memset(&dsnh_info, 0, sizeof(sys_nh_info_dsnh_t));
        CTC_ERROR_RETURN(_sys_usw_nh_get_nhinfo(lchip, nhid, &dsnh_info));
        dsmet_para.aps_bridge_en = 1;
        dsmet_para.dest_id = dsnh_info.gport;
        dsmet_para.next_hop_ptr = dsnh_info.dsnh_offset;
        dsmet_para.end_local_rep = 1;
        dsmet_para.met_offset = met_offset;
        dsmet_para.next_met_entry_ptr = SYS_NH_MET_END_REPLICATE_OFFSET;
        dsmet_para.next_ext = dsnh_info.nexthop_ext;
        dsmet_para.is_destmap_profile = dsnh_info.use_destmap_profile;
        CTC_ERROR_RETURN(sys_usw_nh_add_dsmet(lchip, &dsmet_para, 1));
        if (DRV_FROM_AT(lchip))
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_dsfwd1_offset(lchip, nhid, &dsfwd_offset, 1, CTC_FEATURE_NEXTHOP));
        }
        else
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_dsfwd_offset(lchip, nhid, &dsfwd_offset, 1, CTC_FEATURE_NEXTHOP));
        }
        cmd = DRV_IOR(DRV_FROM_AT(lchip)? DsFwd1_t : DsFwd_t, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DRV_IOCTL(lchip, dsfwd_offset/2, cmd, &dsfwd));
        if (0 == GetDsFwd(V, isHalf_f, &dsfwd))
        {
            SetDsFwd(V, apsBridgeEn_f, &dsfwd, 0);
            SetDsFwd(V, destMap_f, &dsfwd, SYS_ENCODE_MCAST_IPE_DESTMAP(met_offset));
        }
        else
        {
            if (dsfwd_offset % 2 == 0)
            {
                GetDsFwdDualHalf(A, g_0_dsFwdHalf_f,   &dsfwd,   &dsfwd_half);
            }
            else
            {
                GetDsFwdDualHalf(A, g_1_dsFwdHalf_f,   &dsfwd,   &dsfwd_half);
            }
            SetDsFwdHalf(V, destMap_f, &dsfwd_half, SYS_ENCODE_MCAST_IPE_DESTMAP(met_offset));
            SetDsFwdHalf(V, apsBridgeEn_f, &dsfwd_half, 0);
            if (dsfwd_offset % 2 == 0)
            {
                SetDsFwdDualHalf(A, g_0_dsFwdHalf_f,   &dsfwd,   &dsfwd_half);
            }
            else
            {
                SetDsFwdDualHalf(A, g_1_dsFwdHalf_f,   &dsfwd,   &dsfwd_half);
            }
        }
        cmd = DRV_IOW(DRV_FROM_AT(lchip)? DsFwd1_t : DsFwd_t, DRV_ENTRY_FLAG);

        DRV_IOCTL(lchip, dsfwd_offset/2, cmd, &dsfwd);
    }

    if (p_nhinfo->hdr.nh_entry_type == SYS_NH_TYPE_MPLS)
    {
        p_nh_mpls_info->aps_xcon_met = enable?1:0;
        p_nh_mpls_info->met_offset = met_offset;
    }
    else if (p_nhinfo->hdr.nh_entry_type == SYS_NH_TYPE_SRV6)
    {
        p_nh_srv6_info->aps_xcon_met = enable?1:0;
        p_nh_srv6_info->met_offset = met_offset;
    }
    else
    {
         p_nh_aps_info->aps_xcon_met = 1;
    }

    return CTC_E_NONE;
}
int32
sys_usw_nh_add_vxlan_edit_profile(uint8 lchip, sys_nh_vxlan_hw_profile_t* p_profile)
{
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    uint32 cmd;
    uint8  loop;
    uint8  length;
    uint8  free_idx = 0xFF;
    sys_nh_vxlan_hw_profile_t* p_node;
    EpePktProcVxlanRsvCtl_m vxlan_rsv;
    uint8  step;

    if(NULL == p_nh_master->vxlan_edit_profile)
    {
        return CTC_E_NOT_SUPPORT;
    }
    length = CTC_OFFSET_OF(sys_nh_vxlan_hw_profile_t, calc_key_len);
    for(loop=0; loop < SYS_NH_MAX_VXLAN_PROFLLE; loop++)
    {
        p_node = p_nh_master->vxlan_edit_profile + loop;
        if(p_node->ref_cnt && (0 == sal_memcmp(p_profile, p_node, length)))
        {
            if(p_node->ref_cnt != 0xFFFFFF) /*ref cnt == 0xFFFFFF is static, no need to increase ref cnt*/
            {
                p_node->ref_cnt++;
            }
            p_profile->profile_idx = loop;
            return CTC_E_NONE;
        }
        else if(free_idx == 0xFF && 0 == p_node->ref_cnt)
        {
            free_idx = loop;
        }
    }
    if(0xFF == free_idx)
    {
        return CTC_E_NO_RESOURCE;
    }

    p_node = p_nh_master->vxlan_edit_profile + free_idx;
    sal_memcpy(p_node, p_profile, length);
    p_profile->profile_idx = free_idx;
    p_node->ref_cnt = 1;
    cmd = DRV_IOR(EpePktProcVxlanRsvCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &vxlan_rsv));

    step = DRV_FROM_TMM(lchip) ? EpePktProcVxlanRsvCtl_g_1_rsv1_f - EpePktProcVxlanRsvCtl_g_0_rsv1_f :\
        EpePktProcVxlanRsvCtl_gVxlanRsvField_1_vxlanFlags_f - EpePktProcVxlanRsvCtl_gVxlanRsvField_0_vxlanFlags_f;
    if(DRV_FROM_TMM(lchip))
    {
    SetEpePktProcVxlanRsvCtl(V, g_0_udpDestPort_f+step*free_idx, &vxlan_rsv, p_profile->udp_dest_port);
    SetEpePktProcVxlanRsvCtl(V, g_0_rsv1_f+step*free_idx, &vxlan_rsv, p_profile->rsv1);
    SetEpePktProcVxlanRsvCtl(V, g_0_rsv2_f+step*free_idx, &vxlan_rsv, p_profile->rsv2);
    SetEpePktProcVxlanRsvCtl(V, g_0_rsv3_f+step*free_idx, &vxlan_rsv, p_profile->rsv3);
    SetEpePktProcVxlanRsvCtl(V, g_0_rsv7_f+step*free_idx, &vxlan_rsv, p_profile->rsv7);
    SetEpePktProcVxlanRsvCtl(V, g_0_vxlanFlags_f+step*free_idx, &vxlan_rsv, p_profile->flags);
    SetEpePktProcVxlanRsvCtl(V, g_0_rsv3AsEType_f+step*free_idx, &vxlan_rsv, p_profile->rsv3_as_etype);
    SetEpePktProcVxlanRsvCtl(V, g_0_rsv3AsProtoSel_f+step*free_idx, &vxlan_rsv, p_profile->rsv3_as_protocol);
    SetEpePktProcVxlanRsvCtl(V, g_0_vxlanFormatWithPolicyGroup_f+step*free_idx, &vxlan_rsv, p_profile->with_policy_group);
    }
    else
    {
    /*TM process*/
    SetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanFlags_f+step*free_idx, &vxlan_rsv, p_profile->flags);
    SetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanFormatWithPolicyGroup_f+step*free_idx, &vxlan_rsv, p_profile->with_policy_group);
    SetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanReserved1_f+step*free_idx, &vxlan_rsv, p_profile->rsv1<<16|p_profile->rsv2<<8|p_profile->rsv3);
    SetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanReserved2_f+step*free_idx, &vxlan_rsv, p_profile->rsv7);
    }
    cmd = DRV_IOW(EpePktProcVxlanRsvCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &vxlan_rsv));
    return CTC_E_NONE;
}

int32
sys_usw_nh_remove_vxlan_edit_profile(uint8 lchip, sys_nh_vxlan_hw_profile_t* p_profile)
{
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    sys_nh_vxlan_hw_profile_t* p_node;

    if(p_profile->profile_idx  == 0)
    {
        return CTC_E_NONE;
    }
    if(NULL == p_nh_master->vxlan_edit_profile)
    {
        return CTC_E_NOT_SUPPORT;
    }
    p_node = p_nh_master->vxlan_edit_profile + p_profile->profile_idx;

    /*ref cnt == 0xFFFFFF is static, no need to decrease ref cnt*/
    if(p_node->ref_cnt && p_node->ref_cnt != 0xFFFFFF)
    {
        p_node->ref_cnt--;
    }
    return CTC_E_NONE;
}

int32
sys_usw_nh_update_offset_ref_cnt(uint8 lchip, uint32 nhid, uint32 is_add)
{
    sys_nh_info_com_t* p_nh_info = NULL;
    sys_nh_offset_t* p_nh_offset = NULL;
    sys_nh_offset_t nh_offset;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nh_info));
    if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH))
    {
        return CTC_E_NONE;
    }

    sal_memset(&nh_offset, 0, sizeof(nh_offset));
    nh_offset.nh_offset = p_nh_info->hdr.dsnh_offset;
    p_nh_offset = ctc_hash_lookup(g_usw_nh_master[lchip]->nh_offset_hash, &nh_offset);
    if (is_add)/*add*/
    {
        if (p_nh_offset)
        {
            p_nh_offset->ref_cnt++;
        }
        else
        {
            p_nh_offset = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_offset_t));
            if (NULL == p_nh_offset)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
                return CTC_E_NO_MEMORY;
            }
            p_nh_offset->nh_offset = p_nh_info->hdr.dsnh_offset;
            p_nh_offset->ref_cnt = 1;
            if (NULL == ctc_hash_insert(g_usw_nh_master[lchip]->nh_offset_hash, p_nh_offset))
            {
                mem_free(p_nh_offset);
                return CTC_E_NO_MEMORY;
            }
        }
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "ref_cnt = %d\n", p_nh_offset->ref_cnt);
    }
    else/*del*/
    {
        if (p_nh_offset)
        {
            p_nh_offset->ref_cnt = p_nh_offset->ref_cnt? (p_nh_offset->ref_cnt - 1) : 0;
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "ref_cnt = %d\n", p_nh_offset->ref_cnt);
            if (p_nh_offset->ref_cnt)
            {
                return CTC_E_NONE;
            }
            p_nh_offset = (sys_nh_offset_t*)ctc_hash_remove(g_usw_nh_master[lchip]->nh_offset_hash, &nh_offset);
            if (p_nh_offset)
            {
                mem_free(p_nh_offset);
            }
        }
        else
        {
            return CTC_E_NOT_EXIST;
        }
    }
    return CTC_E_NONE;
}

uint32
sys_usw_nh_get_offset_ref_cnt(uint8 lchip, uint32 offset)
{
    sys_nh_offset_t* p_nh_offset = NULL;
    sys_nh_offset_t nh_offset;
    sal_memset(&nh_offset, 0, sizeof(nh_offset));
    nh_offset.nh_offset = offset;
    p_nh_offset = ctc_hash_lookup(g_usw_nh_master[lchip]->nh_offset_hash, &nh_offset);
    if (p_nh_offset)
    {
        return p_nh_offset->ref_cnt;
    }
    return 0;
}

#define __________init___________
/**
 @brief This function is used to init resolved dsnexthop for bridge

 */
STATIC int32
_sys_usw_nh_dsnh_init_for_brg(uint8 lchip, sys_nh_offset_attr_t* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_nexthop_t dsnh;
    uint8 offset = 0;

    CTC_PTR_VALID_CHECK(p_offset_attr);
    sal_memset(&dsnh, 0, sizeof(dsnh));

    offset = SYS_DSNH4WREG_INDEX_FOR_BRG;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);

    p_offset_attr->offset_base = nhp_ptr;
    p_offset_attr->entry_size = 1;
    p_offset_attr->entry_num = 1;

    SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh);

    dsnh.svlan_tagged = TRUE;
    dsnh.payload_operation = SYS_NH_OP_BRIDGE;
    dsnh.dest_vlan_ptr = SYS_DSNH_DESTVLANPTR_SPECIAL;
    dsnh.offset = nhp_ptr;
    dsnh.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
    dsnh.destVlanPtrDeriveMode = 1;

    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL,
                                                       offset, &dsnh));

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_nh_dsnh_init_for_ol_brg(uint8 lchip, sys_nh_offset_attr_t* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_nexthop_t dsnh;
    uint8 offset = 0;

    CTC_PTR_VALID_CHECK(p_offset_attr);
    sal_memset(&dsnh, 0, sizeof(dsnh));

    offset = SYS_DSNH4WREG_INDEX_FOR_OL_BRG;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);

    p_offset_attr->offset_base = nhp_ptr;
    p_offset_attr->entry_size = 1;
    p_offset_attr->entry_num = 1;

    SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh);

    dsnh.svlan_tagged = FALSE;
    dsnh.vlan_xlate_mode = 1;
    dsnh.dvp_tbl_valid = 1;

    dsnh.payload_operation = SYS_NH_OP_BRIDGE_VPLS;
    dsnh.dest_vlan_ptr = SYS_DSNH_DESTVLANPTR_SPECIAL;
    dsnh.offset = nhp_ptr;
    dsnh.share_type = SYS_NH_SHARE_TYPE_VLANTAG;

    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL,
                                                       offset, &dsnh));

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_nh_dsnh_init_for_stk_igs_edit(uint8 lchip)
{
    uint32 nhp_ptr = 0;
    sys_nexthop_t dsnh;
    uint8 offset = 0;
    sys_dsl3edit_tunnelv4_t l3edit;
    uint32 l3_edit_ptr = 0;
    uint32 xedit_ptr= 0;
    sys_dsl3edit_fp_t fp;
    int32 ret = CTC_E_NONE;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    sys_nh_offset_attr_t* p_offset_attr = NULL;

    sal_memset(&dsnh, 0, sizeof(dsnh));
    sal_memset(&l3edit, 0, sizeof(l3edit));
    sal_memset(&fp, 0, sizeof(fp));

    offset = SYS_DSNH4WREG_INDEX_FOR_STK_IGS_EDT;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);
    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING )
    {
        p_offset_attr = &p_nh_master->sys_nh_resolved_offset[SYS_NH_RES_OFFSET_TYPE_STK_IGS_EDIT_BRG];
        p_offset_attr->offset_base = nhp_ptr;
        p_offset_attr->entry_size = 1;
        p_offset_attr->entry_num = 1;
        return CTC_E_NONE;
    }

    CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_XFP_EDIT, 1, &xedit_ptr));
    CTC_ERROR_GOTO(
       sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_XFP_EDIT, xedit_ptr, &fp), ret, roll_back_0);

   /*alloc edit*/
    l3edit.l3_rewrite_type = DRV_ENUM(DRV_L3EDITTYPE_NONE);
    l3edit.ds_type   = SYS_NH_DS_TYPE_L3EDIT;
    l3edit.xedit_ptr = xedit_ptr;
    CTC_ERROR_GOTO(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4,
                                   1, &l3_edit_ptr), ret, roll_back_0);
    CTC_ERROR_GOTO(
       sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4, l3_edit_ptr, &l3edit), ret, roll_back_1);

    p_offset_attr = &p_nh_master->sys_nh_resolved_offset[SYS_NH_RES_OFFSET_TYPE_STK_IGS_EDIT_BRG];
    p_offset_attr->offset_base = nhp_ptr;
    p_offset_attr->entry_size = 1;
    p_offset_attr->entry_num = 1;

    SYS_USW_NH_DSNH_SET_DEFAULT_COS_ACTION(dsnh);

    dsnh.is_nexthop8_w = 1;
    dsnh.svlan_tagged = TRUE;
    dsnh.payload_operation = SYS_NH_OP_BRIDGE;
    dsnh.dest_vlan_ptr = SYS_DSNH_DESTVLANPTR_SPECIAL;
    dsnh.offset = nhp_ptr;
    dsnh.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
    dsnh.outer_edit_ptr = l3_edit_ptr;
    dsnh.outer_edit_valid    = 1;
    dsnh.outer_edit_ptr_type = 1;/*L3edit*/
    dsnh.outer_edit_location = 0;

    CTC_ERROR_GOTO(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL,
                                                       offset, &dsnh), ret, roll_back_1);
    p_nh_master->rsv_l3edit_for_igs_edit = l3_edit_ptr;
    p_nh_master->rsv_xedit_for_igs_edit = xedit_ptr;
    return CTC_E_NONE;
roll_back_1:
    sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4, 1, l3_edit_ptr);

roll_back_0:
    sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_FP, 1, xedit_ptr);
    return ret;
}

/**
 @brief This function is used to init resolved dsnexthop for mirror
 */
STATIC int32
_sys_usw_nh_dsnh_init_for_mirror(uint8 lchip, sys_nh_offset_attr_t* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_nexthop_t dsnh;
    uint8 offset = 0;

    CTC_PTR_VALID_CHECK(p_offset_attr);
    sal_memset(&dsnh, 0, sizeof(dsnh));

    offset = SYS_DSNH4WREG_INDEX_FOR_MIRROR;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);

    p_offset_attr->offset_base = nhp_ptr;
    p_offset_attr->entry_size = 1;
    p_offset_attr->entry_num = 1;

    dsnh.vlan_xlate_mode = TRUE;
    dsnh.payload_operation = SYS_NH_OP_MIRROR;
    dsnh.tagged_mode = TRUE;
    dsnh.share_type = SYS_NH_SHARE_TYPE_VLANTAG;
    dsnh.offset = nhp_ptr;

    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL,
                                                       offset, &dsnh));

    return CTC_E_NONE;

}


/**
 @brief This function is used to init resolved dsnexthop for egress bypass
 */
STATIC int32
_sys_usw_nh_dsnh_init_for_bypass(uint8 lchip, sys_nh_offset_attr_t* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_nexthop_t dsnh;
    uint8 offset = 0;

    CTC_PTR_VALID_CHECK(p_offset_attr);
    sal_memset(&dsnh, 0, sizeof(dsnh));

    offset = SYS_DSNH4WREG_INDEX_FOR_BYPASS;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);

    p_offset_attr->offset_base = nhp_ptr;
    p_offset_attr->entry_size = 1;
    p_offset_attr->entry_num = 1;

    dsnh.next_hop_bypass = TRUE;
    dsnh.offset = nhp_ptr;
    dsnh.is_nexthop8_w = 1;
    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL,
                                                       offset, &dsnh));

    return CTC_E_NONE;

}
STATIC int32
_sys_usw_nh_dsnh_init_for_twamp(uint8 lchip, sys_nh_offset_attr_t* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_nexthop_t dsnh;
    uint8 offset = 0;

    CTC_PTR_VALID_CHECK(p_offset_attr);
    sal_memset(&dsnh, 0, sizeof(dsnh));

    offset = SYS_DSNH4WREG_INDEX_FOR_TWAMP_UPD_CHKSUM;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);

    p_offset_attr->offset_base = nhp_ptr;
    p_offset_attr->entry_size = 1;
    p_offset_attr->entry_num = 1;

    dsnh.next_hop_bypass = TRUE;
    dsnh.offset = nhp_ptr;
    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL,offset, &dsnh));

    return CTC_E_NONE;

}

/**
 @brief This function is used to init resolved dsnexthop for egress bpe ecid transparent
 */
int32
_sys_usw_nh_dsnh_init_for_bpe_transparent(uint8 lchip, sys_nh_offset_attr_t* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_nexthop_t dsnh;
    uint8 offset = 0;

    CTC_PTR_VALID_CHECK(p_offset_attr);
    sal_memset(&dsnh, 0, sizeof(dsnh));

    offset = SYS_DSNH4WREG_INDEX_FOR_BPE_TRANSPARENT;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);

    p_offset_attr->offset_base = nhp_ptr;
    p_offset_attr->entry_size = 1;
    p_offset_attr->entry_num = 1;

    dsnh.next_hop_bypass = TRUE;
    dsnh.offset = nhp_ptr;
    dsnh.is_nexthop8_w = 1;
    dsnh.ecid_valid = 1;
    dsnh.ecid = 0;
    dsnh.share_type =  SYS_NH_SHARE_TYPE_VLANTAG;

    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL,
                                                       offset, &dsnh));

    return CTC_E_NONE;

}


/**
 This function is used to init resolved dsFwd for loopback to itself
 */
STATIC int32
_sys_usw_nh_dsfwd_init_for_reflective(uint8 lchip, uint16* p_offset_attr)
{
    uint32 dsfwd_ptr = 0;
    uint32 nhp_ptr = 0;
    uint8 offset = 0;
    sys_fwd_t dsfwd;

    offset = SYS_DSNH4WREG_INDEX_FOR_BYPASS;
    nhp_ptr = SYS_NH_BUILD_INT_OFFSET(offset);
    sal_memset(&dsfwd, 0, sizeof(dsfwd));
    dsfwd.force_back_en = 1;
    dsfwd.nexthop_ptr = nhp_ptr;
    dsfwd.nexthop_ext = 1;
    dsfwd.is_6w = 1;
    CTC_ERROR_RETURN(
    sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_FWD, 2, &dsfwd_ptr));

    CTC_ERROR_RETURN(
    sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_FWD, dsfwd_ptr, &dsfwd));
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN(
        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_FWD1, 2, dsfwd_ptr));
        dsfwd.is_dsfwd1 = 1;
        CTC_ERROR_RETURN(
        sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_FWD1, dsfwd_ptr, &dsfwd));
    }
    *p_offset_attr = dsfwd_ptr;

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_nh_dsfwd_init_for_ip_tunnel_reroute(uint8 lchip, uint16* p_offset_attr)
{
    uint32 dsfwd_ptr = 0;
    sys_fwd_t dsfwd;
    uint16 lport = 0;
    uint8 gchip = 0;

    CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_FWD1, 1, &dsfwd_ptr));

    lport = SYS_RSV_PORT_IP_TUNNEL;
    sys_usw_get_gchip_id(lchip, &gchip);

    sal_memset(&dsfwd, 0, sizeof(dsfwd));
    dsfwd.nexthop_ptr = 0;
    dsfwd.nexthop_ext = 0;
    dsfwd.dest_map = SYS_ENCODE_DESTMAP(gchip, lport);

    dsfwd.is_6w = 0;

    dsfwd.is_dsfwd1 = 1;
    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_FWD1, dsfwd_ptr, &dsfwd));

    *p_offset_attr = dsfwd_ptr;

    return CTC_E_NONE;

}


/**
 This function is used to init resolved dsFwd 0 for drop
*/
STATIC int32
_sys_usw_nh_dsfwd_init_for_drop(uint8 lchip)
{
    sys_nh_param_dsfwd_t dsfwd_param;
    uint8 gchip = 0;

    sal_memset(&dsfwd_param, 0, sizeof(dsfwd_param));
    dsfwd_param.drop_pkt = 1;
    dsfwd_param.dsfwd_offset = 0;
    dsfwd_param.dest_id = 0xFFFF;
    CTC_ERROR_RETURN(sys_usw_nh_write_entry_dsfwd(lchip, &dsfwd_param));
    if (DRV_FROM_AT(lchip))
    {
        dsfwd_param.is_dsfwd1 = 1;
        CTC_ERROR_RETURN(sys_usw_nh_write_entry_dsfwd(lchip, &dsfwd_param));
    }

    sal_memset(&dsfwd_param, 0, sizeof(dsfwd_param));
    CTC_ERROR_RETURN(sys_usw_get_gchip_id(lchip, &gchip));
    dsfwd_param.drop_pkt = 0;
    dsfwd_param.dsfwd_offset = 1;
    dsfwd_param.dest_id = SYS_ENCODE_DESTMAP(gchip, SYS_RSV_PORT_DROP_ID);
    dsfwd_param.nexthop_ext = 0;
    dsfwd_param.dsnh_offset = 0;
    CTC_ERROR_RETURN(sys_usw_nh_write_entry_dsfwd(lchip, &dsfwd_param));
    if (DRV_FROM_AT(lchip))
    {
        dsfwd_param.is_dsfwd1 = 1;
        CTC_ERROR_RETURN(sys_usw_nh_write_entry_dsfwd(lchip, &dsfwd_param));
    }

    return CTC_E_NONE;
}

/**
 @brief This function is used to init resolved l2edit6w  for ecmp interface
 */
STATIC int32
_sys_usw_nh_l2edit_init_for_ecmp_if(uint8 lchip, uint16* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_dsl2edit_eth_t l2edit;

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING )
    {
        return CTC_E_NONE;
    }
    sal_memset(&l2edit, 0, sizeof(l2edit));
    l2edit.ds_type  = SYS_NH_DS_TYPE_L2EDIT;
    if (DRV_IS_DUET2(lchip) || DRV_IS_TSINGMA(lchip))
    {
        l2edit.l2_rewrite_type  = SYS_NH_L2EDIT_TYPE_ETH_8W;
    }
    else
    {
        l2edit.l2_rewrite_type  = DRV_ENUM(DRV_L2EDITTYPE_AUTOETH2X);
        l2edit.update_mac_sa = 1;
    }
    l2edit.is_8w = 1;
    l2edit.use_port_mac = 1;

    CTC_ERROR_RETURN(
    sys_usw_nh_offset_alloc_with_multiple(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 2,
                                   2, &nhp_ptr));
    CTC_ERROR_RETURN(
       sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W, nhp_ptr, &l2edit));


    *p_offset_attr = nhp_ptr;

    return CTC_E_NONE;

}

/**
 @brief This function is used to init resolved l2edit3w  for srv6 reroute
 */
STATIC int32
_sys_usw_nh_l2edit_init_for_srv6(uint8 lchip, uint16* p_offset_attr)
{
    uint32 nhp_ptr = 0;
    sys_dsl2edit_eth_t l2edit;

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING )
    {
        return CTC_E_NONE;
    }

    sal_memset(&l2edit, 0, sizeof(l2edit));
    l2edit.ds_type  = SYS_NH_DS_TYPE_L2EDIT;
    l2edit.l2_rewrite_type  = DRV_ENUM(DRV_L2EDITTYPE_ADDETH1X);

    CTC_ERROR_RETURN(
    sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W,
                                   1, &nhp_ptr));
    CTC_ERROR_RETURN(
       sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, nhp_ptr, &l2edit));

    *p_offset_attr = nhp_ptr;

    return CTC_E_NONE;

}

/**
 @brief This function is used to initilize dynamic offset, inclue offset pool,
        and resolved offset
*/
STATIC int32
_sys_usw_nh_offset_init(uint8 lchip, sys_usw_nh_master_t* p_master, ctc_nh_global_cfg_t* nh_cfg)
{
    sys_usw_opf_t opf;
    uint16 tbl_id = 0;
    uint32 tbl_entry_num[6] = {0};
    uint32 glb_tbl_entry_num[6] = {0};
    uint8  dyn_tbl_idx = 0;
    uint8  max_dyn_tbl_idx = 0;
    uint32  entry_enum = 0, nh_glb_entry_num = 0;
    uint32 nexthop_entry_num = 0;
    uint32 spme_entry = 0;
    uint8  dyn_tbl_opf_type = 0;
    uint8  loop = 0;
    uint8  loop1 = 0;
    uint8  loop1_max = 0;
    uint16 rsv_local_met_num = 0;
    uint8  opf_type = 0;


    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    /*1. DsFwd */
    tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FWD].table_id;
    sys_usw_ftm_get_dynamic_table_info(lchip, tbl_id,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, NULL);
    dyn_tbl_opf_type  = OPF_NH_DYN1_SRAM + dyn_tbl_idx;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FWD].opf_pool_type = dyn_tbl_opf_type;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FWD_HALF].opf_pool_type = dyn_tbl_opf_type;
    tbl_entry_num[dyn_tbl_idx]  = entry_enum;
    max_dyn_tbl_idx = dyn_tbl_idx;
    CTC_MAX_VALUE_CHECK(entry_enum, 0x10000);/* max ptr is 64K in hw*/

    /*2. DsFwd1 */
    if (DRV_FROM_AT(lchip))
    {
        tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FWD1].table_id;
        sys_usw_ftm_get_dynamic_table_info(lchip, tbl_id,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, NULL);
        dyn_tbl_opf_type  = OPF_NH_DYN1_SRAM + dyn_tbl_idx;
        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FWD1].opf_pool_type = dyn_tbl_opf_type;
        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FWD_HALF1].opf_pool_type = dyn_tbl_opf_type;
        tbl_entry_num[dyn_tbl_idx]  = entry_enum;
        max_dyn_tbl_idx = (dyn_tbl_idx > max_dyn_tbl_idx) ? dyn_tbl_idx : max_dyn_tbl_idx;
        CTC_MAX_VALUE_CHECK(entry_enum, 0x10000);/* max ptr is 64K in hw*/
    }

    /*3. DsMet */
    if(DRV_FROM_AT(lchip))
    {
        uint32 entry_num1 = 0;
        tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET].table_id;
        sys_usw_ftm_get_dynamic_table_info(lchip, tbl_id,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, &rsv_local_met_num);

        CTC_ERROR_RETURN(sys_usw_ftm_query_table_entry_num(lchip, DsMetEntrySlim1X_t, &entry_num1));

        if(entry_num1)
        {
            entry_enum += entry_num1;
            p_master->met_ext_mode = SYS_MET_MODE_EXT;
            MCHIP_CAP(SYS_CAP_NH_MC_PBMP_NUM) = 256;
        }
        else
        {
            p_master->met_ext_mode = SYS_MET_MODE_NORMAL;
        }
        drv_set_met_mode(lchip, p_master->met_ext_mode);
    }
    else
    {
        tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET].table_id;
        sys_usw_ftm_get_dynamic_table_info(lchip, tbl_id,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, &rsv_local_met_num);
    }

    /*global entry number from FTM module is mcast group number*/
    nh_glb_entry_num = (nh_glb_entry_num << p_master->met_mode);
    dyn_tbl_opf_type  = OPF_NH_DYN1_SRAM + dyn_tbl_idx;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET].opf_pool_type = dyn_tbl_opf_type;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET_6W].opf_pool_type = dyn_tbl_opf_type;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET_12W].opf_pool_type = dyn_tbl_opf_type;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET_RSVED].opf_pool_type = dyn_tbl_opf_type;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET_RSVED].alloc_dir = rsv_local_met_num ? 1:0;
    tbl_entry_num[dyn_tbl_idx]  = entry_enum;
    glb_tbl_entry_num[dyn_tbl_idx]  = nh_glb_entry_num;
    max_dyn_tbl_idx = (dyn_tbl_idx > max_dyn_tbl_idx) ? dyn_tbl_idx : max_dyn_tbl_idx;

    /*4. DsNexthop */
    tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_NEXTHOP_4W].table_id;
    sys_usw_ftm_get_dynamic_table_info(lchip, tbl_id ,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, NULL);
    dyn_tbl_opf_type  = OPF_NH_DYN1_SRAM + dyn_tbl_idx;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_NEXTHOP_4W].opf_pool_type = dyn_tbl_opf_type;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_NEXTHOP_8W].opf_pool_type = dyn_tbl_opf_type;
    tbl_entry_num[dyn_tbl_idx]  = entry_enum;
    nexthop_entry_num = entry_enum;
    if (p_master->pkt_nh_edit_mode != SYS_NH_EDIT_MODE_IGS)
    {
        glb_tbl_entry_num[dyn_tbl_idx]  = nh_glb_entry_num;
    }
    max_dyn_tbl_idx = (dyn_tbl_idx > max_dyn_tbl_idx) ? dyn_tbl_idx : max_dyn_tbl_idx;

    /*5. DsEdit Inner */
    if(DRV_FROM_AT(lchip))
    {
        sys_usw_ftm_get_dynamic_table_info(lchip, DsL3EditAddMpls1X0_t,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, NULL);
        dyn_tbl_opf_type  = OPF_NH_DYN1_SRAM + dyn_tbl_idx;
        tbl_entry_num[dyn_tbl_idx]  = entry_enum;
        max_dyn_tbl_idx = (dyn_tbl_idx > max_dyn_tbl_idx) ? dyn_tbl_idx : max_dyn_tbl_idx;
        for (loop = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_FROM; loop <= SYS_NH_ENTRY_TYPE_L3EDIT_INNER_TO; loop++)
        {
            p_master->nh_table_info_array[loop].opf_pool_type = dyn_tbl_opf_type;
        }
        CTC_MAX_VALUE_CHECK(entry_enum, 0x10000);/* max ptr is 64K in hw*/
    }

    /*6. DsEdit */
    tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L3EDIT_MPLS].table_id;
    sys_usw_ftm_get_dynamic_table_info(lchip, tbl_id,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, NULL);
    dyn_tbl_opf_type  = OPF_NH_DYN1_SRAM + dyn_tbl_idx;
    tbl_entry_num[dyn_tbl_idx]  = entry_enum;
    max_dyn_tbl_idx = (dyn_tbl_idx > max_dyn_tbl_idx) ? dyn_tbl_idx : max_dyn_tbl_idx;
    for (loop = SYS_NH_ENTRY_TYPE_L2EDIT_FROM; loop <= SYS_NH_ENTRY_TYPE_L3EDIT_TO; loop++)
    {
        p_master->nh_table_info_array[loop].opf_pool_type = dyn_tbl_opf_type;
    }
    CTC_MAX_VALUE_CHECK(entry_enum, 0x10000);/* max ptr is 64K in hw*/

    /*Init  global dsnexthop & dsMet offset*/
    dyn_tbl_idx = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_NEXTHOP_4W].opf_pool_type - OPF_NH_DYN1_SRAM;
    if (DRV_FROM_AT(lchip))
    {
    /*
        uint32 entry_num = 0;
        CTC_ERROR_RETURN(sys_usw_ftm_query_table_entry_num(lchip, DsNextHopIdMapPointer_t, &entry_num));
        if (entry_num)
        {
            glb_tbl_entry_num[dyn_tbl_idx ] = 0;
        }
        */
    }
    if (p_master->pkt_nh_edit_mode == SYS_NH_EDIT_MODE_IGS || (glb_tbl_entry_num[dyn_tbl_idx ] == 0))
    {
        p_master->max_glb_nh_offset  = 0;
    }
    else
    {
        p_master->max_glb_nh_offset  = glb_tbl_entry_num[dyn_tbl_idx ];
        p_master->p_occupid_nh_offset_bmp = (uint32*)mem_malloc(MEM_NEXTHOP_MODULE,
                                                                (sizeof(uint32) * (p_master->max_glb_nh_offset / BITS_NUM_OF_WORD + 1)));
        if (NULL == p_master->p_occupid_nh_offset_bmp)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_master->p_occupid_nh_offset_bmp, 0,  (sizeof(uint32) * (p_master->max_glb_nh_offset / BITS_NUM_OF_WORD + 1)));

    }

    dyn_tbl_idx = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_MET].opf_pool_type - OPF_NH_DYN1_SRAM;
    p_master->max_glb_met_offset  = glb_tbl_entry_num[dyn_tbl_idx ];
    if (p_master->max_glb_met_offset)
    {
        p_master->p_occupid_met_offset_bmp = (uint32*)mem_malloc(MEM_NEXTHOP_MODULE, (sizeof(uint32) * (p_master->max_glb_met_offset / BITS_NUM_OF_WORD + 1)));
        if (NULL == p_master->p_occupid_met_offset_bmp)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_master->p_occupid_met_offset_bmp, 0,  (sizeof(uint32) * (p_master->max_glb_met_offset / BITS_NUM_OF_WORD + 1)));
        sys_usw_nh_set_glb_nh_offset(lchip, 0, 2, 1);
    }

    /*When stacking enable, all mcast group should default set drop*/
    if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_STACKING))
    {
        sys_met_t dsmet;
        uint32 dsmet_idx = 0;
        sal_memset(&dsmet, 0, sizeof(dsmet));
        dsmet.dest_id = SYS_NH_MET_DROP_UCAST_ID;
        dsmet.end_local_rep = 1;
        dsmet.next_met_entry_ptr = 0xFFFF;
        for(dsmet_idx=0; dsmet_idx< p_master->max_glb_met_offset; dsmet_idx++)
        {
            CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_MET, dsmet_idx, &dsmet));
        }
    }

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));

    for (loop = 0; loop <= max_dyn_tbl_idx; loop++)
    {
        dyn_tbl_idx = loop;


        /*all nexthop opf min offset should be greater than 2*/

        if (0 == glb_tbl_entry_num[dyn_tbl_idx])
        {
            glb_tbl_entry_num[dyn_tbl_idx]++;
            glb_tbl_entry_num[dyn_tbl_idx]++;
        }

        if (tbl_entry_num[dyn_tbl_idx] < glb_tbl_entry_num[dyn_tbl_idx])
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory, Global tbl entry exceed max table num \n");
            return CTC_E_NO_MEMORY;
        }

        tbl_entry_num[dyn_tbl_idx] = tbl_entry_num[dyn_tbl_idx] - glb_tbl_entry_num[dyn_tbl_idx];

        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        if (OPF_NH_DYN3_SRAM == loop)/*dsmet*/
        {
            loop1_max = MCHIP_CAP(SYS_CAP_LOCAL_SLICE_NUM);
        }
        else
        {
            loop1_max = 1;
        }
        for (loop1 = 0; loop1 < loop1_max; loop1++)
        {
            opf.pool_index = OPF_NH_DYN1_SRAM + loop + loop1*OPF_NH_DYN_MAX;
            CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, glb_tbl_entry_num[dyn_tbl_idx], tbl_entry_num[dyn_tbl_idx]));
        }

    }

    /*init dsmet reserved offset, for keepalive member and mcast profile*/
    if(rsv_local_met_num)
    {
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_DYN3_SRAM;
        CTC_ERROR_RETURN(sys_usw_opf_init_reverse_size(lchip, &opf, rsv_local_met_num));
    }

    tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W].table_id;
    sys_usw_ftm_query_table_entry_num(lchip, tbl_id, &entry_enum);
    dyn_tbl_opf_type = OPF_NH_OUTER_L2EDIT;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W].opf_pool_type = dyn_tbl_opf_type;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W].opf_pool_type = dyn_tbl_opf_type;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = dyn_tbl_opf_type;
    MCHIP_CAP(SYS_CAP_NH_OUTER_L2_EDIT_NUM) = entry_enum*2;

    if (g_usw_nh_master[lchip]->mpls_spme_dis)
    {
        /*use spme resource to expand arp spec*/
        sys_usw_ftm_query_table_entry_num(lchip, p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L3EDIT_SPME].table_id, &spme_entry);
        entry_enum += spme_entry;
    }
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, entry_enum*2-1));

    dyn_tbl_opf_type = OPF_NH_OUTER_SPME;
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L3EDIT_SPME].opf_pool_type = dyn_tbl_opf_type;
    if (g_usw_nh_master[lchip]->mpls_spme_dis)
    {
        /*spme first 2 ptr must reserve, cannot using*/
        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 2, (entry_enum-spme_entry));
    }
    else
    {
        tbl_id = p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L3EDIT_SPME].table_id;
        sys_usw_ftm_query_table_entry_num(lchip, tbl_id, &entry_enum);
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = dyn_tbl_opf_type;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 2, entry_enum*2-2));
    }

    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_L2EDIT_VLAN_PROFILE].opf_pool_type = OPF_NH_L2EDIT_VLAN_PROFILE;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_L2EDIT_VLAN_PROFILE;
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, 63));


    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_DESTMAP_PROFILE].opf_pool_type = OPF_NH_DESTMAP_PROFILE;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_DESTMAP_PROFILE;
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, (MCHIP_CAP(SYS_CAP_NH_DESTMAP_PROFILE_NUM)-1)));
    sys_usw_ftm_query_table_entry_num(lchip, DsL3EditFlexAluProfile_t,  &entry_enum);
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FP_ALU_PROFILE].opf_pool_type = OPF_NH_FP_ALU_PROFILE;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_FP_ALU_PROFILE;
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, entry_enum - 1));

    sys_usw_ftm_query_table_entry_num(lchip, DsFlexEditInsertHeaderTemplate_t,  &entry_enum);
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FP_DATA_PROFILE].opf_pool_type = OPF_NH_FP_DATA_PROFILE;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_FP_DATA_PROFILE;
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, entry_enum - 1));

    sys_usw_ftm_query_table_entry_num(lchip, DsPktRwL3ChkSumMaskProfile_t,  &entry_enum);
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FP_L3CHKSUM_PROFILE].opf_pool_type = OPF_NH_FP_L3CHKSUM_PROFILE;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_FP_L3CHKSUM_PROFILE;
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 2, entry_enum - 2));

    sys_usw_ftm_query_table_entry_num(lchip, DsPktRwL4ChkSumMaskProfile_t,  &entry_enum);
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_FP_L4CHKSUM_PROFILE].opf_pool_type = OPF_NH_FP_L4CHKSUM_PROFILE;
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_FP_L4CHKSUM_PROFILE;
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 2, entry_enum - 2));

#if defined(ARCTIC)
    if (DRV_FROM_AT(lchip))
    {
        sys_usw_ftm_query_table_entry_num(lchip, DsXEditRwFlex_t,  &entry_enum);
        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_XFP_EDIT].opf_pool_type = OPF_NH_XFP_EDIT;
        if(entry_enum)
        {
            opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
            opf.pool_index = OPF_NH_XFP_EDIT;
            CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, entry_enum - 1));
        }

        sys_usw_ftm_query_table_entry_num(lchip, DsXEditFlexAluProfile_t,  &entry_enum);
        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_XFP_ALU_PROFILE].opf_pool_type = OPF_NH_XFP_ALU_PROFILE;
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_XFP_ALU_PROFILE;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, entry_enum - 1));

        sys_usw_ftm_query_table_entry_num(lchip, DsXEditInsertHeaderTemplate_t,  &entry_enum);
        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_XFP_DATA_PROFILE].opf_pool_type = OPF_NH_XFP_DATA_PROFILE;
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_XFP_DATA_PROFILE;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, entry_enum - 1));
    }
#endif

    sys_usw_ftm_query_table_entry_num(lchip, DsQMsgReplicationList_t,  &entry_enum);
    p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_LOGIC_REP].opf_pool_type = OPF_NH_LOGIC_REP;
    if(entry_enum)
    {
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_LOGIC_REP;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 0, (entry_enum - 1)));
    }

    /* For Arctic, 0~32K for logicport, 32K~48K for logicportext(underlay), 48K~64K for other(srv6) */
    if(DRV_FROM_AT(lchip))
    {
        sys_usw_ftm_query_table_entry_num(lchip, DsEgressLogicDestPort_t,  &entry_enum);
        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_LOGIC_DEST_PORT].opf_pool_type = OPF_NH_LOGIC_PORT;
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_LOGIC_PORT;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, MCHIP_CAP(SYS_CAP_NH_LOGIC_DEST_PORT_EXT_BASE) + MCHIP_CAP(SYS_CAP_NH_MAX_LOGIC_DEST_PORT_EXT) + 1, MCHIP_CAP(SYS_CAP_NH_MAX_LOGIC_DEST_PORT_EXT) + 1));

        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_LOGIC_DEST_PORT_EXT].opf_pool_type = OPF_NH_LOGIC_PORT_EXT;

        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_LOGIC_PORT_EXT;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, MCHIP_CAP(SYS_CAP_NH_LOGIC_DEST_PORT_EXT_BASE), MCHIP_CAP(SYS_CAP_NH_MAX_LOGIC_DEST_PORT_EXT) + 1));
    }

    if (g_usw_nh_master[lchip]->ldp_mac_profile_en)
    {
        sys_usw_ftm_query_table_entry_num(lchip, DsEgressPortMac_t,  &entry_enum);
        p_master->nh_table_info_array[SYS_NH_ENTRY_TYPE_LDP_MAC_PROFILE].opf_pool_type = OPF_NH_LDP_MAC_PROFILE;
        opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
        opf.pool_index = OPF_NH_LDP_MAC_PROFILE;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, (entry_enum - 1)));
    }

    p_master->internal_nexthop_base = 0xFFF;
    /*usually, the global nh offset is N*1024 size*/
    if(p_master->max_glb_nh_offset > 0xFFF0)
    {
        sys_usw_nh_set_glb_nh_offset(lchip, 0xFFF0, 16, 1);
    }
    else if (nexthop_entry_num >= 64*1024)
    {
        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 16, 0xFFF0);
    }
    /* DsNexthop offset for bridge, */
    CTC_ERROR_RETURN(_sys_usw_nh_dsnh_init_for_brg(lchip,
                                                          &(p_master->sys_nh_resolved_offset \
                                                          [SYS_NH_RES_OFFSET_TYPE_BRIDGE_NH])));
    /* DsNexthop offset for bridge, */
    CTC_ERROR_RETURN(_sys_usw_nh_dsnh_init_for_ol_brg(lchip,
                                                          &(p_master->sys_nh_resolved_offset \
                                                          [SYS_NH_RES_OFFSET_TYPE_OL_BRIDGE_NH])));

    /* DsNexthop for bypassall*/
    CTC_ERROR_RETURN(_sys_usw_nh_dsnh_init_for_bypass(lchip,
                                                             &(p_master->sys_nh_resolved_offset \
                                                             [SYS_NH_RES_OFFSET_TYPE_BYPASS_NH])));

    /* DsNexthop for mirror*/
    CTC_ERROR_RETURN(_sys_usw_nh_dsnh_init_for_mirror(lchip,
                                                             &(p_master->sys_nh_resolved_offset \
                                                             [SYS_NH_RES_OFFSET_TYPE_MIRROR_NH])));
    CTC_ERROR_RETURN(_sys_usw_nh_dsnh_init_for_twamp(lchip,
                                                             &(p_master->sys_nh_resolved_offset \
                                                             [SYS_NH_RES_OFFSET_TYPE_TWAMP_CHKSUM_NH])));
    /* l2edit for ipmc phy if*/
    CTC_ERROR_RETURN(_sys_usw_nh_l2edit_init_for_ecmp_if(lchip,
                                                             &(p_master->ecmp_if_resolved_l2edit)));

    /* l2edit for srv6 reroute*/
    if (DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_RETURN(_sys_usw_nh_l2edit_init_for_srv6(lchip,
                                                             &(p_master->srv6_resolved_l2edit)));
    }

    /* DsNexthop and l2edit for ingress edit mode, the egress chip bypass xedit */
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN(_sys_usw_nh_dsnh_init_for_stk_igs_edit(lchip));
    }

    /* dsfwd for reflective (loopback)*/
    CTC_ERROR_RETURN(_sys_usw_nh_dsfwd_init_for_reflective(lchip,
                                                                  &(p_master->reflective_resolved_dsfwd_offset)));

    /* dsfwd for ip tunnel (reroute)*/
    if (DRV_FROM_AT(lchip))
    {
        CTC_ERROR_RETURN(_sys_usw_nh_dsfwd_init_for_ip_tunnel_reroute(lchip,
                                                               &(p_master->reroute_dsfwd_offset)));
    }

    CTC_ERROR_RETURN(_sys_usw_nh_dsfwd_init_for_drop(lchip));

    /* init for ip tunnel*/
    CTC_ERROR_RETURN(sys_usw_nh_ip_tunnel_init(lchip));

    /* init opf for ecmp groupid */
    if (p_master->h_ecmp_en && DRV_FROM_TMM(lchip))
    {
        uint32 ecmp_group_num = 0;
        ecmp_group_num = MCHIP_CAP(SYS_CAP_NH_ECMP_GROUP_ID_NUM) + 1;

        CTC_ERROR_RETURN(sys_usw_opf_init(lchip, &opf_type, 2, "opf-ecmp-group"));
        g_usw_nh_master[lchip]->ecmp_group_opf_type = opf_type;
        opf.pool_type = g_usw_nh_master[lchip]->ecmp_group_opf_type;

        opf.pool_index = 0;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf,  ecmp_group_num / 2, ecmp_group_num / 2));

        opf.pool_index = 1;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, ecmp_group_num / 2 - 1));
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_opf_init(lchip, &opf_type, 1, "opf-ecmp-group"));
        g_usw_nh_master[lchip]->ecmp_group_opf_type = opf_type;
        opf.pool_type = g_usw_nh_master[lchip]->ecmp_group_opf_type;
        opf.pool_index = 0;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, 1, MCHIP_CAP(SYS_CAP_NH_ECMP_GROUP_ID_NUM)));
    }

    /* init opf for ecmp member*/
    if (p_master->h_ecmp_en && DRV_FROM_TMM(lchip))
    {
        uint32 member_half_num = MCHIP_CAP(SYS_CAP_NH_ECMP_MEMBER_NUM)/2;

        CTC_ERROR_RETURN(sys_usw_opf_init(lchip, &opf_type, 2,  "opf-ecmp-member"));
        g_usw_nh_master[lchip]->ecmp_member_opf_type = opf_type;
        opf.pool_type = g_usw_nh_master[lchip]->ecmp_member_opf_type;
        /*pool 1 used for h-ecmp*/
        opf.pool_index = 1;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, SYS_NH_ECMP_RESEVED_NUM, (member_half_num-SYS_NH_ECMP_RESEVED_NUM)));
        g_usw_nh_master[lchip]->ecmp_drop_mem_base[1] = 0;

        /*pool 0 used for underlay ecmp*/
        opf.pool_index = 0;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, member_half_num + SYS_NH_ECMP_RESEVED_NUM, member_half_num - SYS_NH_ECMP_RESEVED_NUM));
        g_usw_nh_master[lchip]->ecmp_drop_mem_base[0] = member_half_num;
    }
    else
    {
        CTC_ERROR_RETURN(sys_usw_opf_init(lchip, &opf_type, 1,  "opf-ecmp-member"));
        g_usw_nh_master[lchip]->ecmp_member_opf_type = opf_type;
        opf.pool_type = g_usw_nh_master[lchip]->ecmp_member_opf_type;
        opf.pool_index = 0;
        CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, SYS_NH_ECMP_RESEVED_NUM, (MCHIP_CAP(SYS_CAP_NH_ECMP_MEMBER_NUM)-SYS_NH_ECMP_RESEVED_NUM)));
    }
    /* init for mcast group nhid vector*/
    p_master->mcast_group_vec = ctc_vector_init(CTC_VEC_BLOCK_NUM(p_master->max_glb_met_offset, SYS_NH_MCAST_GROUP_MAX_BLK_SIZE), SYS_NH_MCAST_GROUP_MAX_BLK_SIZE);
    if (NULL == p_master->mcast_group_vec)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    g_usw_nh_master[lchip]->hecmp_mem_num = 4;
    return CTC_E_NONE;
}

STATIC uint32
_sys_usw_nh_edit_spool_hash_make(sys_nh_db_edit_t* p_data_input)
{
    return (ctc_hash_caculate(sizeof(ds0_t), p_data_input->ds) + p_data_input->edit_type);
}


STATIC bool
_sys_usw_nh_edit_spool_hash_cmp(sys_nh_db_edit_t* p_data, sys_nh_db_edit_t* p_data_input)
{
    ds0_t ds;
    uint8 size = sizeof(ds0_t);
    void* p_ds = &ds;
    if (!p_data || !p_data_input)
    {
        return TRUE;
    }

    if (p_data->edit_type != p_data_input->edit_type)
    {
        return FALSE;
    }

    sal_memset(ds, 0, sizeof(ds));
    if (0xFFFFFF == p_data->offset)/*for spool add error rollback, 0xFFFFFF is return from opf*/
    {
        return  TRUE;
    }
    else
    {
        if (sys_usw_nh_get_asic_table(p_data_input->lchip, p_data->edit_type, p_data->offset, &ds) != CTC_E_NONE)/*lchip from input data*/
        {
            return FALSE;
        }
        if (SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W == p_data_input->edit_type)
        {
            uint32 len = DRV_TABLE_ENTRY_SIZE(p_data_input->lchip, DsL2Edit6WOuter_t) / 2;
            if (CTC_IS_BIT_SET(p_data->offset, 0))
            {
                p_ds = (uint8*)p_ds + len;
            }
            size = len;
        }
    }

    if (!sal_memcmp(p_ds, (p_data_input->ds), size))
    {
        return TRUE;
    }

    return FALSE;
}

int32
_sys_usw_nh_edit_spool_alloc_index(sys_nh_db_edit_t* p_edit, void* user_data)
{
    uint8 lchip = *(uint8*)user_data;
    int32 ret = 0;
    uint32 offset = 0;

    if(CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        offset = p_edit->offset;
        ret = sys_usw_nh_offset_alloc_from_position(lchip, p_edit->edit_type, 1, offset);
        goto end;
    }
    ret = sys_usw_nh_offset_alloc(lchip, p_edit->edit_type, 1, &offset);
    p_edit->offset = offset;

end:
    if(ret)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "spool alloc index failed,  line=%d\n",__LINE__);
    }
    return ret;
}


int32
_sys_usw_nh_edit_spool_free_index(sys_nh_db_edit_t* p_edit, void* user_data)
{
    uint8 lchip = *(uint8*)user_data;
    int32 ret = 0;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    ret = sys_usw_nh_offset_free(lchip, p_edit->edit_type, 1, p_edit->offset);
    if(ret)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, "spool fress index failed,  offset=%d\n",p_edit->offset);
        return ret;
    }

    return ret;
}


STATIC int32
_sys_usw_nh_arp_hash_make(sys_nh_db_arp_t* p_data)
{
    uint32 arp_id = p_data->arp_id;
    return ctc_hash_caculate(sizeof(uint32), &arp_id);
}

STATIC bool
_sys_usw_nh_arp_hash_cmp(sys_nh_db_arp_t* p_data0, sys_nh_db_arp_t* p_data1)
{
    if (!p_data0 || !p_data1)
    {
        return TRUE;
    }

    if (p_data0->arp_id == p_data1->arp_id)
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_nh_srh_hash_make(sys_nh_db_srh_t* p_data)
{
    return ctc_hash_caculate(sizeof(uint32), &(p_data->srh_id));
}

STATIC bool
_sys_usw_nh_srh_hash_cmp(sys_nh_db_srh_t* p_data0, sys_nh_db_srh_t* p_data1)
{
    if (!p_data0 || !p_data1)
    {
        return TRUE;
    }

    if (p_data0->srh_id == p_data1->srh_id)
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_nh_vp_hash_make(sys_nh_db_ol_tunnel_t* p_data)
{
    return ctc_hash_caculate(sizeof(uint32), &(p_data->logic_port));
}

STATIC bool
_sys_usw_nh_vp_hash_cmp(sys_nh_db_ol_tunnel_t* p_data0, sys_nh_db_ol_tunnel_t* p_data1)
{
    if (!p_data0 || !p_data1)
    {
        return TRUE;
    }

    if (p_data0->logic_port == p_data1->logic_port)
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_nh_hash_make(sys_nh_info_com_t* p_data)
{
    return ctc_hash_caculate(sizeof(uint32), &(p_data->hdr.nh_id));
}

STATIC bool
_sys_usw_nh_hash_cmp(sys_nh_info_com_t* p_data0, sys_nh_info_com_t* p_data1)
{
    if (!p_data0 || !p_data1)
    {
        return TRUE;
    }

    if (p_data0->hdr.nh_id == p_data1->hdr.nh_id)
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_nh_hash_ext_make(sys_nh_info_ext_t* p_data)
{
    return ctc_hash_caculate(sizeof(uint32), &(p_data->nh_id));
}

STATIC bool
_sys_usw_nh_hash_ext_cmp(sys_nh_info_ext_t* p_data0, sys_nh_info_ext_t* p_data1)
{
    if (!p_data0 || !p_data1)
    {
        return TRUE;
    }

    if (p_data0->nh_id == p_data1->nh_id)
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_nh_offset_hash_make(sys_nh_offset_t* p_data)
{
    return ctc_hash_caculate(sizeof(uint32), &(p_data->nh_offset));
}

STATIC bool
_sys_usw_nh_offset_hash_cmp(sys_nh_offset_t* p_data0, sys_nh_offset_t* p_data1)
{
    if (!p_data0 || !p_data1)
    {
        return TRUE;
    }

    if (p_data0->nh_offset == p_data1->nh_offset)
    {
        return TRUE;
    }

    return FALSE;
}

STATIC int32
_sys_usw_nh_id_init(uint8 lchip, sys_usw_nh_master_t* p_master)
{
    sys_usw_opf_t opf;
    uint32 internal_nh_num;
    uint8 opf_type = 0;
    ctc_hash_t* p_nh_hash = NULL;
    uint32 start_internal_nhid = SYS_NH_INTERNAL_NHID_BASE;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    internal_nh_num = SYS_NH_INTERNAL_NHID_MAX_SIZE;

    /*1. Creat hash, use hash to store internal nh_info*/
    p_nh_hash = ctc_hash_create(SYS_NH_NHID_HASH_SIZE/CTC_HASH_1K_BLOCK_SIZE,
                                                    CTC_HASH_1K_BLOCK_SIZE,
                                                    (hash_key_fn)_sys_usw_nh_hash_make,
                                                    (hash_cmp_fn)_sys_usw_nh_hash_cmp);
    if (!p_nh_hash)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    p_master->nhid_hash = p_nh_hash;



    p_nh_hash = ctc_hash_create(SYS_NH_NHID_HASH_SIZE/CTC_HASH_1K_BLOCK_SIZE,
                                                    CTC_HASH_1K_BLOCK_SIZE,
                                                    (hash_key_fn)_sys_usw_nh_hash_ext_make,
                                                    (hash_cmp_fn)_sys_usw_nh_hash_ext_cmp);
    if (!p_nh_hash)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    p_master->nhid_ext_hash = p_nh_hash;

    /*2. Init nhid pool, use opf to alloc/free internal nhid*/
    CTC_ERROR_RETURN(sys_usw_opf_init(lchip, &opf_type, OPF_NH_DYN_MAX * MCHIP_CAP(SYS_CAP_LOCAL_SLICE_NUM), "opf-nexthop"));
    p_master->nh_opf_type = opf_type;

    /*NHID resource :
     External nhid range: 0~0x7FFFFFFF
     Internal nhid range: 0x80000000~0xFFFFFFFF
    */
    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type = p_master->nh_opf_type;
    opf.pool_index = OPF_NH_NHID_INTERNAL;
    CTC_ERROR_RETURN(sys_usw_opf_init_offset(lchip, &opf, start_internal_nhid, internal_nh_num));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_tunnel_id_init(uint8 lchip, sys_usw_nh_master_t* p_master, uint16 max_tunnel_id)
{
    ctc_vector_t* p_tunnel_id_vec;
    uint16 block_size = (max_tunnel_id + SYS_NH_TUNNEL_ID_MAX_BLK_NUM - 1) / SYS_NH_TUNNEL_ID_MAX_BLK_NUM;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    /*1. Creat vector, use vector to store internal nh_info*/
    p_tunnel_id_vec = ctc_vector_init(SYS_NH_TUNNEL_ID_MAX_BLK_NUM, block_size);
    if (NULL == p_tunnel_id_vec)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
			return CTC_E_NO_MEMORY;

    }
    p_master->tunnel_id_vec = p_tunnel_id_vec;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_arp_id_init(uint8 lchip, sys_usw_nh_master_t* p_master, uint32 arp_number)
{
    ctc_hash_t* p_arp_id_hash = NULL;

    arp_number = arp_number/SYS_HASH_SIZE_COMPRESS_RATE_4;
    p_arp_id_hash = ctc_hash_create(arp_number/CTC_HASH_1K_BLOCK_SIZE,
                                                    CTC_HASH_1K_BLOCK_SIZE,
                                                    (hash_key_fn)_sys_usw_nh_arp_hash_make,
                                                    (hash_cmp_fn)_sys_usw_nh_arp_hash_cmp);
    if (!p_arp_id_hash)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
			return CTC_E_NO_MEMORY;

    }

    p_master->arp_id_hash = p_arp_id_hash;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_srh_id_init(uint8 lchip, sys_usw_nh_master_t* p_master, uint16 srh_number)
{
    ctc_hash_t* p_hash = NULL;
    p_hash = ctc_hash_create(srh_number/CTC_HASH_512_BLOCK_SIZE, CTC_HASH_512_BLOCK_SIZE,
                                                    (hash_key_fn)_sys_usw_nh_srh_hash_make,
                                                    (hash_cmp_fn)_sys_usw_nh_srh_hash_cmp);
    if (!p_hash)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    p_master->srh_id_hash = p_hash;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_vp_tunnel_init(uint8 lchip, sys_usw_nh_master_t* p_master)
{
    ctc_hash_t* p_hash = NULL;
    uint32 hash_size = 0;

    hash_size = MCHIP_CAP(SYS_CAP_NH_MAX_LOGIC_DEST_PORT)/SYS_HASH_SIZE_COMPRESS_RATE_4;
    p_hash = ctc_hash_create((hash_size + CTC_HASH_1K_BLOCK_SIZE)/CTC_HASH_1K_BLOCK_SIZE, CTC_HASH_1K_BLOCK_SIZE,
                                                    (hash_key_fn)_sys_usw_nh_vp_hash_make,
                                                    (hash_cmp_fn)_sys_usw_nh_vp_hash_cmp);
    if (!p_hash)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    p_master->ol_tunnel_hash = p_hash;


    if (DRV_IS_TSINGMA(lchip))
    {
        p_hash = ctc_hash_create(CTC_HASH_1K_BLOCK_SIZE / CTC_HASH_64_BLOCK_SIZE,
                                    CTC_HASH_64_BLOCK_SIZE,
                                    (hash_key_fn)_sys_usw_nh_offset_hash_make,
                                    (hash_cmp_fn)_sys_usw_nh_offset_hash_cmp);
        if (!p_hash)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;
        }
        p_master->nh_offset_hash = p_hash;
    }
    return CTC_E_NONE;
}


STATIC int32
_sys_usw_nh_register_callback(uint8 lchip, sys_usw_nh_master_t* p_master, uint16 nh_param_type,
                                    p_sys_nh_create_cb_t nh_create_cb, p_sys_nh_delete_cb_t nh_del_cb,
                                    p_sys_nh_update_cb_t nh_update_cb, p_sys_nh_get_cb_t nh_get_cb)
{
    p_master->callbacks_nh_create[nh_param_type] = nh_create_cb;
    p_master->callbacks_nh_delete[nh_param_type] = nh_del_cb;
    p_master->callbacks_nh_update[nh_param_type] = nh_update_cb;
    p_master->callbacks_nh_get[nh_param_type] = nh_get_cb;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_callback_init(uint8 lchip, sys_usw_nh_master_t* p_master)
{
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);



    /* 1. Ucast bridge */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_BRGUC,
                                                         sys_usw_nh_create_brguc_cb,
                                                         sys_usw_nh_delete_brguc_cb,
                                                         sys_usw_nh_update_brguc_cb,
                                                         NULL));



    /* 2. Mcast bridge */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_MCAST,
                                                         &sys_usw_nh_create_mcast_cb,
                                                         &sys_usw_nh_delete_mcast_cb,
                                                         &sys_usw_nh_update_mcast_cb,
                                                         NULL));



    /* 3. IPUC */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_IPUC,
                                                         &sys_usw_nh_create_ipuc_cb,
                                                         &sys_usw_nh_delete_ipuc_cb,
                                                         &sys_usw_nh_update_ipuc_cb,
                                                         &sys_usw_nh_get_ipuc_cb));

    /* 4. ECMP */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_ECMP,
                                                         &sys_usw_nh_create_ecmp_cb,
                                                         &sys_usw_nh_delete_ecmp_cb,
                                                         &sys_usw_nh_update_ecmp_cb,
                                                         &sys_usw_nh_get_ecmp_cb));

    /* 5. MPLS */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_MPLS,
                                                         &sys_usw_nh_create_mpls_cb,
                                                         &sys_usw_nh_delete_mpls_cb,
                                                         &sys_usw_nh_update_mpls_cb,
                                                         &sys_usw_nh_get_mpls_cb));

    /* 6. Drop */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_DROP,
                                                         &sys_usw_nh_create_special_cb,
                                                         &sys_usw_nh_delete_special_cb, NULL, NULL));

    /* 7. ToCPU */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_TOCPU,
                                                         &sys_usw_nh_create_special_cb,
                                                         &sys_usw_nh_delete_special_cb, NULL, NULL));

    /* 8. Unresolve */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_UNROV,
                                                         &sys_usw_nh_create_special_cb,
                                                         &sys_usw_nh_delete_special_cb, NULL, NULL));

    /* 9. ILoop */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_ILOOP,
                                                         &sys_usw_nh_create_iloop_cb,
                                                         &sys_usw_nh_delete_iloop_cb,
                                                         &sys_usw_nh_update_iloop_cb,
                                                         NULL));

    /* 10. rspan */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_RSPAN,
                                                         &sys_usw_nh_create_rspan_cb,
                                                         &sys_usw_nh_delete_rspan_cb,
                                                         NULL,
                                                         NULL));

    /* 11. ip-tunnel */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_IP_TUNNEL,
                                                         &sys_usw_nh_create_ip_tunnel_cb,
                                                         &sys_usw_nh_delete_ip_tunnel_cb,
                                                         &sys_usw_nh_update_ip_tunnel_cb,
                                                         &sys_usw_nh_get_ip_tunnel_cb));

    /* 12. trill-tunnel */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_TRILL,
                                                         &sys_usw_nh_create_trill_cb,
                                                         &sys_usw_nh_delete_trill_cb,
                                                         &sys_usw_nh_update_trill_cb,
                                                         NULL));

    /* 13. misc */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_MISC,
                                                         &sys_usw_nh_create_misc_cb,
                                                         &sys_usw_nh_delete_misc_cb,
                                                         &sys_usw_nh_update_misc_cb,
                                                         &sys_usw_nh_get_misc_cb));
    /* 14. wlan-tunnel */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_WLAN_TUNNEL,
                                                         &sys_usw_nh_create_wlan_tunnel_cb,
                                                         &sys_usw_nh_delete_wlan_tunnel_cb,
                                                         &sys_usw_nh_update_wlan_tunnel_cb,
                                                         NULL));
    /* 15. srv6 */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_SRV6,
                                                         &sys_usw_nh_create_srv6_cb,
                                                         &sys_usw_nh_delete_srv6_cb,
                                                         &sys_usw_nh_update_srv6_cb,
                                                         &sys_usw_nh_get_srv6_cb));

    /* 16. overlay vni */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_OVERLAY_VNI,
                                                         &sys_usw_nh_create_ol_vni_cb,
                                                         &sys_usw_nh_delete_ol_vni_cb,
                                                         &sys_usw_nh_update_ol_vni_cb,
                                                         &sys_usw_nh_get_ol_vni));
    /* 17. overlay */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_OVERLAY,
                                                         &sys_usw_nh_create_overlay_cb,
                                                         &sys_usw_nh_delete_overlay_cb,
                                                         &sys_usw_nh_update_overlay_cb,
                                                         &sys_usw_nh_get_overlay_cb));

    /* 18. aps-nexthop */
    CTC_ERROR_RETURN(_sys_usw_nh_register_callback(lchip, p_master,
                                                         SYS_NH_TYPE_APS,
                                                         &sys_usw_nh_create_aps_cb,
                                                         &sys_usw_nh_delete_aps_cb,
                                                         &sys_usw_nh_update_aps_cb,
                                                         &sys_usw_nh_get_aps_cb));


    p_master->db_size[SYS_NH_TYPE_MCAST]       = sizeof(sys_nh_info_mcast_t);
    p_master->db_size[SYS_NH_TYPE_BRGUC]       = sizeof(sys_nh_info_brguc_t);
    p_master->db_size[SYS_NH_TYPE_IPUC]        = sizeof(sys_nh_info_ipuc_t);
    p_master->db_size[SYS_NH_TYPE_MPLS]        = sizeof(sys_nh_info_mpls_t);
    p_master->db_size[SYS_NH_TYPE_ECMP]        = sizeof(sys_nh_info_ecmp_t);
    p_master->db_size[SYS_NH_TYPE_DROP]        = sizeof(sys_nh_info_special_t);
    p_master->db_size[SYS_NH_TYPE_TOCPU]       = sizeof(sys_nh_info_special_t);
    p_master->db_size[SYS_NH_TYPE_UNROV]       = sizeof(sys_nh_info_special_t);
    p_master->db_size[SYS_NH_TYPE_ILOOP]       = sizeof(sys_nh_info_special_t);
    p_master->db_size[SYS_NH_TYPE_RSPAN]       = sizeof(sys_nh_info_rspan_t);
    p_master->db_size[SYS_NH_TYPE_IP_TUNNEL]   = sizeof(sys_nh_info_ip_tunnel_t);
    p_master->db_size[SYS_NH_TYPE_TRILL]       = sizeof(sys_nh_info_trill_t);
    p_master->db_size[SYS_NH_TYPE_MISC]        = sizeof(sys_nh_info_misc_t);
    p_master->db_size[SYS_NH_TYPE_WLAN_TUNNEL] = sizeof(sys_nh_info_wlan_tunnel_t);
    p_master->db_size[SYS_NH_TYPE_SRV6]        = sizeof(sys_nh_info_srv6_t);
    p_master->db_size[SYS_NH_TYPE_OVERLAY_VNI] = sizeof(sys_nh_info_ol_vni_t);
    p_master->db_size[SYS_NH_TYPE_OVERLAY]     = sizeof(sys_nh_info_overlay_t);
    p_master->db_size[SYS_NH_TYPE_APS]         = sizeof(sys_nh_info_aps_t);

    return CTC_E_NONE;
}

/**
 @brief This function is used to create and init nexthop module master data
 */
STATIC int32
_sys_usw_nh_master_new(uint8 lchip, sys_usw_nh_master_t** pp_nexthop_master, uint32 boundary_of_extnl_intnl_nhid, uint16 max_tunnel_id, uint32 arp_num, uint16 srh_num)
{
    sys_usw_nh_master_t* p_master = NULL;
    ctc_spool_t spool;
    uint8 dyn_tbl_idx = 0;
    uint32 entry_enum = 0;
    uint32 nh_glb_entry_num = 0;
    int32 ret = CTC_E_NONE;
    uint32 tbl_id = 0;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
    if (NULL == pp_nexthop_master || (NULL != *pp_nexthop_master))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Invalid pointer \n");
        return CTC_E_INVALID_PTR;

    }

    /*1. allocate memory for nexthop master*/
    p_master = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_usw_nh_master_t));
    if (NULL == p_master)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;

    }
    sal_memset(p_master, 0, sizeof(sys_usw_nh_master_t));
    p_master->ipmc_dsnh_offset = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(uint32)*MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM));
    if (NULL == p_master->ipmc_dsnh_offset)
    {
       SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
       return CTC_E_NO_MEMORY;
    }

    sal_memset(p_master->ipmc_dsnh_offset, 0, sizeof(uint32)*MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM));
    p_master->pon_ipmc_dsnh_offset = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(uint32)*MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM));
    if (NULL == p_master->pon_ipmc_dsnh_offset)
    {
        mem_free(p_master->ipmc_dsnh_offset);
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    sal_memset(p_master->pon_ipmc_dsnh_offset, 0, sizeof(uint32)*MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM));
    sal_memset(&spool, 0, sizeof(ctc_spool_t));

    /*2. l2&l3 edit spool init */
    tbl_id = DRV_FROM_TMM(lchip)? DsL3EditAddMpls1X_t : DsL3EditMpls3W_t;
    sys_usw_ftm_get_dynamic_table_info(lchip, tbl_id,  &dyn_tbl_idx, &entry_enum, &nh_glb_entry_num, NULL);
    if (0 == entry_enum)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " l2&l3 edit have no resource!! \n");
        ret = CTC_E_NOT_INIT;
        goto clean;
    }

    spool.lchip = lchip;
    spool.block_num = CTC_VEC_BLOCK_NUM(entry_enum, SYS_NH_L2EDIT_HASH_BLOCK_NUM);
    spool.block_size = SYS_NH_L2EDIT_HASH_BLOCK_NUM;
    spool.max_count = entry_enum;
    spool.user_data_size = CTC_OFFSET_OF(sys_nh_db_edit_t, calc_len);
    spool.spool_key = (hash_key_fn) _sys_usw_nh_edit_spool_hash_make;
    spool.spool_cmp = (hash_cmp_fn) _sys_usw_nh_edit_spool_hash_cmp;
    spool.spool_alloc = (spool_alloc_fn)_sys_usw_nh_edit_spool_alloc_index;
    spool.spool_free = (spool_free_fn)_sys_usw_nh_edit_spool_free_index;
    p_master->p_edit_spool = ctc_spool_create(&spool);
    if (!p_master->p_edit_spool)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        ret = CTC_E_NO_MEMORY;
        goto clean;
    }

    /*5. Nexthop hash init*/
    CTC_ERROR_GOTO(_sys_usw_nh_id_init(lchip, p_master), ret, clean);

    /*6. Tunnel id vector init*/
    CTC_ERROR_GOTO(_sys_usw_nh_tunnel_id_init(lchip, p_master, max_tunnel_id), ret, clean);

    /*7. Arp id hash init*/
    CTC_ERROR_GOTO(_sys_usw_nh_arp_id_init(lchip, p_master, arp_num), ret, clean);

    /*8. SRH id hash init*/
    if (DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_GOTO(_sys_usw_nh_srh_id_init(lchip, p_master, srh_num), ret, clean);
    }

    p_master->bind_ldp = 0;
    if(DRV_FROM_TMM(lchip) || (DRV_IS_TSINGMA(lchip) && p_master->bind_ldp))
    {
        CTC_ERROR_GOTO(_sys_usw_nh_vp_tunnel_init(lchip, p_master), ret, clean;)
    }

    /*8. Eloop list init*/
    p_master->eloop_list = ctc_slist_new();
    if (p_master->eloop_list == NULL)
    {
        ret = CTC_E_INVALID_PARAM;
        goto clean;
    }

    /*9. logic rep list init*/
    p_master->repli_offset_list = ctc_slist_new();
    if (p_master->repli_offset_list == NULL)
    {
        ret = CTC_E_INVALID_PARAM;
        goto clean1;
    }

    /*10. vxlan edit profile init*/
    if(DRV_FROM_TM(lchip))
    {
        p_master->vxlan_edit_profile = mem_malloc(MEM_NEXTHOP_MODULE, SYS_NH_MAX_VXLAN_PROFLLE*sizeof(sys_nh_vxlan_hw_profile_t));
        if(NULL == p_master->vxlan_edit_profile)
        {
            goto clean2;
        }
        sal_memset(p_master->vxlan_edit_profile, 0, SYS_NH_MAX_VXLAN_PROFLLE*sizeof(sys_nh_vxlan_hw_profile_t));
    }
    /*Return PTR*/
    *pp_nexthop_master = p_master;

    return CTC_E_NONE;
clean2:
    ctc_slist_free(p_master->repli_offset_list);
clean1:
    ctc_slist_free(p_master->eloop_list);
clean:
    mem_free(p_master->pon_ipmc_dsnh_offset);
    mem_free(p_master->ipmc_dsnh_offset);
    mem_free(p_master);
    return ret;
}

sys_nh_db_ol_tunnel_t*
_sys_usw_nh_lkup_tunnel(uint8 lchip, uint32 ldp)
{
    sys_nh_db_ol_tunnel_t tunnel_db;
    sal_memset(&tunnel_db, 0, sizeof(sys_nh_db_ol_tunnel_t));
    tunnel_db.logic_port = ldp;
    return ctc_hash_lookup(g_usw_nh_master[lchip]->ol_tunnel_hash, &tunnel_db);
}

#define __________warmboot___________
STATIC int32
_sys_usw_nh_wb_restore_loop_nh(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_nh_eloop_node_t* p_eloop_node = NULL;
    sys_wb_nh_loop_nh_t wb;
    sys_wb_nh_loop_nh_t *p_wb = &wb;
    uint32 entry_cnt = 0;
    uint8 entry_type;
    int32 ret = 0;
     sys_usw_opf_t opf;

     sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
     opf.pool_type =g_usw_nh_master[lchip]->nh_opf_type;
     opf.multiple = 1;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_loop_nh_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_LOOP_NH);

    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb, 0, sizeof(sys_wb_nh_loop_nh_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;
      p_eloop_node  = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_eloop_node_t));
      if (NULL == p_eloop_node)
      {
          SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
          return CTC_E_NO_MEMORY;
      }
      sal_memset(p_eloop_node, 0, sizeof(sys_nh_eloop_node_t));
      p_eloop_node->edit_ptr = p_wb->edit_ptr;
      p_eloop_node->is_l2edit = p_wb->is_l2edit;
      p_eloop_node->nhid = p_wb->nhid;
      p_eloop_node->ref_cnt = p_wb->ref_cnt;
      p_eloop_node->lb_with_ldp = p_wb->lb_with_ldp;

     ctc_slist_add_tail(g_usw_nh_master[lchip]->eloop_list, &(p_eloop_node->head));

     entry_type = p_wb->is_l2edit?SYS_NH_ENTRY_TYPE_L2EDIT_LPBK:SYS_NH_ENTRY_TYPE_L3EDIT_LPBK;
     opf.pool_index = g_usw_nh_master[lchip]->nh_table_info_array[entry_type].opf_pool_type + OPF_NH_DYN1_SRAM;
     sys_usw_opf_alloc_offset_from_position(lchip, &opf,  1, p_eloop_node->edit_ptr);
      g_usw_nh_master[lchip]->nhtbl_used_cnt[entry_type]++;


    CTC_WB_QUERY_ENTRY_END(p_wb_query);
    done:
    return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_restore_edit2(uint8 lchip, uint8 entry_type, uint32 edit_ptr, uint32* p_out_table)
{
    sys_nh_db_edit_t tmp_db_edit;
    ds0_t ds;
    sys_nh_db_edit_t* p_db_edit = NULL;

    sal_memset(ds, 0, sizeof(ds));
    CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, entry_type, edit_ptr, &ds));/*lchip from input data*/
    if (SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W == entry_type)
    {
        uint32 len = DRV_TABLE_ENTRY_SIZE(lchip, DsL2Edit6WOuter_t) / 2;
        if (CTC_IS_BIT_SET(edit_ptr, 0))
        {
            sal_memcpy((uint8*)&ds, (uint8*)&ds + len, len);
        }
        sal_memset((uint8*)&ds + len, 0, len);
    }
    sal_memset(&tmp_db_edit, 0, sizeof(sys_nh_db_edit_t));
    tmp_db_edit.offset = edit_ptr;
    tmp_db_edit.edit_type = entry_type;
    tmp_db_edit.lchip = lchip;
    tmp_db_edit.ds = &ds;
    CTC_ERROR_RETURN(ctc_spool_add(g_usw_nh_master[lchip]->p_edit_spool, &tmp_db_edit, NULL, &p_db_edit));

    if(p_out_table)
    {
        sal_memcpy(p_out_table, &ds, sizeof(ds0_t));
    }
    return CTC_E_NONE;
}
int32
_sys_usw_nh_wb_restore_edit(uint8 lchip, uint8 entry_type, uint32 edit_ptr)
{
    return _sys_usw_nh_wb_restore_edit2(lchip, entry_type, edit_ptr, NULL);
}
STATIC int32
_sys_usw_nh_wb_mapping_ecmp_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com,sys_wb_nh_info_ecmp_t *p_wb_nh_info)
{
    sys_nh_info_ecmp_t  *p_nh_info = (sys_nh_info_ecmp_t  *)p_nh_info_com;
   /*v5.6.x ecmp only restore 256*/
    p_wb_nh_info->ecmp_cnt = (p_nh_info->ecmp_cnt > CTC_MAX_UINT8_VALUE ) ? CTC_MAX_UINT8_VALUE : p_nh_info->ecmp_cnt;
    p_wb_nh_info->valid_cnt =  (p_nh_info->valid_cnt > CTC_MAX_UINT8_VALUE ) ? CTC_MAX_UINT8_VALUE : p_nh_info->valid_cnt;
    p_wb_nh_info->type =   p_nh_info->type ;
    p_wb_nh_info->failover_en =   p_nh_info->failover_en;

    p_wb_nh_info->ecmp_group_id =  p_nh_info->ecmp_group_id;
    p_wb_nh_info->random_rr_en =  p_nh_info->random_rr_en;
    p_wb_nh_info->stats_valid =   p_nh_info->stats_valid ;
    p_wb_nh_info->gport =   p_nh_info->gport;
    p_wb_nh_info->ecmp_member_base =  p_nh_info->ecmp_member_base ;
    p_wb_nh_info->l3edit_offset_base =   p_nh_info->l3edit_offset_base;
    p_wb_nh_info->l2edit_offset_base =  p_nh_info->l2edit_offset_base ;
    p_wb_nh_info->mem_num = (p_nh_info->mem_num > CTC_MAX_UINT8_VALUE ) ? CTC_MAX_UINT8_VALUE : p_nh_info->mem_num;
    p_wb_nh_info->hecmp_en = p_nh_info->h_ecmp_en;
    p_wb_nh_info->ant_flow_en = p_nh_info->ant_flow_en;
    p_wb_nh_info->ant_flow_base = p_nh_info->ant_flow_base;
    p_wb_nh_info->rsv = 0;
    p_wb_nh_info->rpf_id = p_nh_info->rpf_id;
    p_wb_nh_info->mem_is_tunnel = p_nh_info->mem_is_tunnel;
    p_wb_nh_info->tunnel_is_ldp = p_nh_info->tunnel_is_ldp;
    p_wb_nh_info->srh_replace_ipda = p_nh_info->srh_replace_ipda;

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_misc_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com,
            sys_wb_nh_info_com_t *p_wb_nh_info,uint8 sync)
{
    uint32 cmd = 0;
    sys_nh_info_misc_t  *p_nh_info = (sys_nh_info_misc_t*)p_nh_info_com;

    if (sync)
    {

        p_wb_nh_info->info.misc.dsl2edit_offset = p_nh_info->dsl2edit_offset ;
        p_wb_nh_info->info.misc.dsl3edit_offset = p_nh_info->dsl3edit_offset ;
        p_wb_nh_info->info.misc.gport =  p_nh_info->gport ;
        p_wb_nh_info->info.misc.is_reflective = p_nh_info->is_reflective ;
        p_wb_nh_info->info.misc.misc_nh_type = p_nh_info->misc_nh_type;
        p_wb_nh_info->info.misc.l3edit_entry_type = p_nh_info->l3edit_entry_type;
        p_wb_nh_info->info.misc.next_l3edit_entry_type = p_nh_info->next_l3edit_entry_type;
        p_wb_nh_info->info.misc.l2edit_entry_type = p_nh_info->l2edit_entry_type;
        p_wb_nh_info->info.misc.vlan_profile_id = p_nh_info->vlan_profile_id;
        p_wb_nh_info->info.misc.next_l3edit_offset = p_nh_info->next_l3edit_offset;
        p_wb_nh_info->info.misc.truncated_len = p_nh_info->truncated_len;
        p_wb_nh_info->info.misc.l3ifid = p_nh_info->l3ifid;
        p_wb_nh_info->info.misc.packet_type = p_nh_info->packet_type;
        p_wb_nh_info->info.misc.ctag_op = p_nh_info->ctag_op;
        p_wb_nh_info->info.misc.scos_sl = p_nh_info->scos_sl;
        p_wb_nh_info->info.misc.stag_op = p_nh_info->stag_op;
        p_wb_nh_info->info.misc.svid_sl = p_nh_info->svid_sl;
        p_wb_nh_info->info.misc.ccos_sl = p_nh_info->ccos_sl;
        p_wb_nh_info->info.misc.flag = p_nh_info->flag;
        p_wb_nh_info->info.misc.label_num = p_nh_info->label_num;
        p_wb_nh_info->info.misc.cvlan_edit_type = p_nh_info->cvlan_edit_type;
        p_wb_nh_info->info.misc.svlan_edit_type = p_nh_info->svlan_edit_type;
        p_wb_nh_info->info.misc.cvid_sl = p_nh_info->cvid_sl;
        p_wb_nh_info->info.misc.is_loop_nh =  p_nh_info->is_loop_nh;

    }
    else
    {
        p_nh_info->dsl2edit_offset = p_wb_nh_info->info.misc.dsl2edit_offset;
        p_nh_info->dsl3edit_offset = p_wb_nh_info->info.misc.dsl3edit_offset;
        p_nh_info->gport = p_wb_nh_info->info.misc.gport;
        p_nh_info->is_reflective = p_wb_nh_info->info.misc.is_reflective;
        p_nh_info->misc_nh_type = p_wb_nh_info->info.misc.misc_nh_type;
        p_nh_info->l3edit_entry_type = p_wb_nh_info->info.misc.l3edit_entry_type;
        p_nh_info->next_l3edit_entry_type = p_wb_nh_info->info.misc.next_l3edit_entry_type;
        p_nh_info->l2edit_entry_type = p_wb_nh_info->info.misc.l2edit_entry_type;
        p_nh_info->vlan_profile_id = p_wb_nh_info->info.misc.vlan_profile_id;
        p_nh_info->next_l3edit_offset = p_wb_nh_info->info.misc.next_l3edit_offset;
        p_nh_info->truncated_len = p_wb_nh_info->info.misc.truncated_len;
        p_nh_info->l3ifid = p_wb_nh_info->info.misc.l3ifid;
        p_nh_info->packet_type = p_wb_nh_info->info.misc.packet_type;
        p_nh_info->ctag_op = p_wb_nh_info->info.misc.ctag_op;
        p_nh_info->scos_sl = p_wb_nh_info->info.misc.scos_sl;
        p_nh_info->stag_op = p_wb_nh_info->info.misc.stag_op;
        p_nh_info->svid_sl = p_wb_nh_info->info.misc.svid_sl;
        p_nh_info->ccos_sl = p_wb_nh_info->info.misc.ccos_sl;
        p_nh_info->flag = p_wb_nh_info->info.misc.flag;
        p_nh_info->label_num = p_wb_nh_info->info.misc.label_num;
        p_nh_info->cvlan_edit_type = p_wb_nh_info->info.misc.cvlan_edit_type;
        p_nh_info->svlan_edit_type = p_wb_nh_info->info.misc.svlan_edit_type;
        p_nh_info->cvid_sl = p_wb_nh_info->info.misc.cvid_sl;
        p_nh_info->is_loop_nh =  p_wb_nh_info->info.misc.is_loop_nh;

        if (!p_nh_info->is_loop_nh && CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDIT))
        {
            /*recover l2edit spool*/
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, p_nh_info->l2edit_entry_type, p_nh_info->dsl2edit_offset));
            if (p_nh_info->vlan_profile_id)
            {
                sys_dsl2edit_vlan_edit_t vlan_edit;
                sal_memset(&vlan_edit, 0, sizeof(sys_dsl2edit_vlan_edit_t));

                /*using vlan proflie, recover spool*/
                if (DRV_FROM_TMM(lchip))
                {
                    cmd = DRV_IOR(DsL2EditRwEthVlanActionProfile_t, DRV_ENTRY_FLAG);
                }
                else
                {
                    cmd = DRV_IOR(DsOfEditVlanActionProfile_t, DRV_ENTRY_FLAG);
                }
                DRV_IOCTL(lchip, p_nh_info->vlan_profile_id, cmd, &vlan_edit.data);
                vlan_edit.profile_id = p_nh_info->vlan_profile_id;

                CTC_ERROR_RETURN(ctc_spool_add(g_usw_nh_master[lchip]->p_l2edit_vprof, &vlan_edit, NULL, NULL));
            }
        }

        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L3EDIT))
        {
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, p_nh_info->l3edit_entry_type, p_nh_info->dsl3edit_offset));
            if (p_nh_info->next_l3edit_offset)
            {
                CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, p_nh_info->next_l3edit_entry_type, p_nh_info->next_l3edit_offset));
            }
        }

    }
    return CTC_E_NONE;

}

STATIC int32
_sys_usw_nh_wb_mapping_brguc_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_brguc_t  *p_nh_info = (sys_nh_info_brguc_t  *)p_nh_info_com;

    if (sync)
    {
        p_wb_nh_info->info.brguc.dest_gport = p_nh_info->dest_gport;
        p_wb_nh_info->info.brguc.nh_sub_type = p_nh_info->nh_sub_type ;
        p_wb_nh_info->info.brguc.dest_logic_port =  p_nh_info->dest_logic_port ;
        p_wb_nh_info->info.brguc.service_id =  p_nh_info->service_id ;
        p_wb_nh_info->info.brguc.l2_edit_ptr =  p_nh_info->l2_edit_ptr ;
       p_wb_nh_info->info.brguc.flag  = p_nh_info->flag;
    }
    else
    {

        p_nh_info->dest_gport = p_wb_nh_info->info.brguc.dest_gport;
        p_nh_info->nh_sub_type = p_wb_nh_info->info.brguc.nh_sub_type;
        p_nh_info->dest_logic_port = p_wb_nh_info->info.brguc.dest_logic_port;
        p_nh_info->service_id = p_wb_nh_info->info.brguc.service_id;
        p_nh_info->l2_edit_ptr = p_wb_nh_info->info.brguc.l2_edit_ptr;
        p_nh_info->flag = p_wb_nh_info->info.brguc.flag  ;

        if (p_nh_info->nh_sub_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BASIC || p_nh_info->nh_sub_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BYPASS)
        {
            sys_nh_param_brguc_t brguc_nh;
            sys_hbnh_brguc_node_info_t brguc_node_tmp;
            sys_hbnh_brguc_node_info_t* p_brguc_node;
            uint8 is_add = 0;

            sal_memset(&brguc_nh, 0, sizeof(sys_nh_param_brguc_t));
            brguc_nh.hdr.nh_param_type = SYS_NH_TYPE_BRGUC;
            brguc_nh.hdr.nhid = p_nh_info->hdr.nh_id;
            brguc_nh.hdr.is_internal_nh = TRUE;
            brguc_nh.nh_sub_type = p_nh_info->nh_sub_type;
            brguc_nh.gport = p_nh_info->dest_gport;

            brguc_node_tmp.gport = p_nh_info->dest_gport;
            p_brguc_node = ctc_hash_lookup(p_usw_nh_api_master[lchip]->brguc_info.brguc_hash, &brguc_node_tmp);
            if (NULL == p_brguc_node)
            {
                p_brguc_node = (sys_hbnh_brguc_node_info_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_hbnh_brguc_node_info_t));
                if (NULL == p_brguc_node)
                {
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
                    return CTC_E_NO_MEMORY;

                }
                sal_memset(p_brguc_node, 0, sizeof(sys_hbnh_brguc_node_info_t));
                p_brguc_node->gport = p_nh_info->dest_gport;
                is_add = 1;
            }

            if (brguc_nh.nh_sub_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BASIC)
            {
                p_brguc_node->nhid_brguc  = p_nh_info->hdr.nh_id;
            }
            else if (brguc_nh.nh_sub_type == SYS_NH_PARAM_BRGUC_SUB_TYPE_BYPASS)
            {
                p_brguc_node->nhid_bypass  = p_nh_info->hdr.nh_id;
            }

            if (is_add)
            {
                ctc_hash_insert(p_usw_nh_api_master[lchip]->brguc_info.brguc_hash, p_brguc_node);
            }
            #ifdef WARMBOOT
            if(SYS_GCHIP_IS_REMOTE(lchip, CTC_MAP_GPORT_TO_GCHIP(p_brguc_node->gport)))
            {
                p_usw_nh_api_master[lchip]->brguc_info.rchip_nh_cnt++;
            }
            #endif
        }
    }

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_nh_wb_mapping_special_nhinfo(sys_nh_info_com_t* p_nh_info_com,sys_wb_nh_info_com_t *p_wb_nh_info,uint8 sync)
{
    sys_nh_info_special_t  *p_nh_info = (sys_nh_info_special_t  *)p_nh_info_com;

    if(sync)
    {
        p_wb_nh_info->info.spec.dest_gport = p_nh_info->dest_gport ;
    }
    else
    {
       p_nh_info->dest_gport = p_wb_nh_info->info.spec.dest_gport;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_ipuc_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com,
        sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_ipuc_t  *p_nh_info = (sys_nh_info_ipuc_t  *)p_nh_info_com;
    uint8 entry_type = 0;
    if (sync)
    {
        p_wb_nh_info->info.ipuc.flag =  p_nh_info->flag;
        p_wb_nh_info->info.ipuc.l3ifid =  p_nh_info->l3ifid;
        p_wb_nh_info->info.ipuc.gport =   p_nh_info->gport ;
        p_wb_nh_info->info.ipuc.arp_id =   p_nh_info->arp_id;
        p_wb_nh_info->info.ipuc.is_8w  =  p_nh_info->l2edit_8w;
        p_wb_nh_info->info.ipuc.ldp_ext = p_nh_info->ldp_ext;
        p_wb_nh_info->info.ipuc.ldp_ext_alloc = p_nh_info->ldp_ext_alloc;
        p_wb_nh_info->info.ipuc.adjust_len = p_nh_info->adjust_len;
        p_wb_nh_info->info.ipuc.l2_edit_ptr = 0;
        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDI_3W) ||
            CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDI_6W) ||
            CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDIT))
        {
            p_wb_nh_info->info.ipuc.l2_edit_ptr = p_nh_info->l2_edit_ptr;
        }

    }
    else
    {
        sys_nh_db_arp_t* p_arp = NULL;
        sys_nh_db_arp_nh_node_t* p_arp_nh_node = NULL;

        p_nh_info->flag = p_wb_nh_info->info.ipuc.flag;
        p_nh_info->l3ifid = p_wb_nh_info->info.ipuc.l3ifid;
        p_nh_info->gport = p_wb_nh_info->info.ipuc.gport;
        p_nh_info->arp_id = p_wb_nh_info->info.ipuc.arp_id;
        p_nh_info->l2edit_8w =  p_wb_nh_info->info.ipuc.is_8w;
        p_nh_info->ldp_ext = p_wb_nh_info->info.ipuc.ldp_ext;
        if (p_wb_nh_info->info.ipuc.ldp_ext_alloc)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_LOGIC_DEST_PORT_EXT, 1, p_wb_nh_info->info.ipuc.ldp_ext);
        }
        p_nh_info->adjust_len = p_wb_nh_info->info.ipuc.adjust_len;

        p_nh_info->pd = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_info_ipuc_pdata_t));
        if (NULL == p_nh_info->pd)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_nh_info->pd, 0, sizeof(sys_nh_info_ipuc_pdata_t));

        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV))
        {
            return CTC_E_NONE;
        }

        if (p_nh_info->arp_id)
        {
            sys_nh_db_arp_t* p_arp = NULL;
            p_arp = (sys_usw_nh_lkup_arp_id(lchip, p_nh_info->arp_id));
            if (NULL == p_arp)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                return CTC_E_NOT_EXIST;
            }
            p_arp->ref_cnt++;
        }

        if (p_nh_info->arp_id && !CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_APS_EN))
        {
            p_arp = (sys_usw_nh_lkup_arp_id(lchip, p_nh_info->arp_id));
            if (NULL == p_arp)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                return CTC_E_NOT_EXIST;
            }
            p_arp_nh_node =  mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_arp_nh_node_t));
            if (NULL == p_arp_nh_node)
            {
                return CTC_E_NO_MEMORY;
            }
            sal_memset(p_arp_nh_node, 0, sizeof(sys_nh_db_arp_nh_node_t));
            p_arp_nh_node->nhid = p_nh_info_com->hdr.nh_id;
            if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
            {
                ctc_list_pointer_insert_tail(p_arp->pd->nh_list, &(p_arp_nh_node->head));
            }
            else
            {
                ctc_list_pointer_insert_head(p_arp->pd->nh_list, &(p_arp_nh_node->head));
            }

            p_arp->pd->updateNhp = (updatenh_fn)_sys_usw_nh_ipuc_update_dsnh_cb;
            p_nh_info->pd->p_arp_nh_node = p_arp_nh_node;
        }

        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDI_3W) ||
            CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDI_6W))
        {
            p_nh_info->l2_edit_ptr = p_wb_nh_info->info.ipuc.l2_edit_ptr;
            entry_type = p_nh_info->l2edit_8w? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W;
        }
        else if(CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L2EDIT))
        {
            p_nh_info->l2_edit_ptr = p_wb_nh_info->info.ipuc.l2_edit_ptr;
            entry_type = p_nh_info->l2edit_8w? SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W : SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W;
        }

        if (p_nh_info->l2_edit_ptr)
        {
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_nh_info->l2_edit_ptr));
        }
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_nh_wb_mapping_rspan_nhinfo(sys_nh_info_com_t* p_nh_info_com,sys_wb_nh_info_com_t *p_wb_nh_info,uint8 sync)
{
   sys_nh_info_rspan_t  *p_nh_info = (sys_nh_info_rspan_t  *)p_nh_info_com;
   if(sync)
   {
       p_wb_nh_info->info.rspan.remote_chip = p_nh_info->remote_chip ;
   }
   else
   {
     p_nh_info->remote_chip= p_wb_nh_info->info.rspan.remote_chip;
   }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_ip_tunnel_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_ip_tunnel_t  *p_nh_info = (sys_nh_info_ip_tunnel_t  *)p_nh_info_com;

    uint8 entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W;
    uint8 is_vxlan_v6 = 0;
    uint32 cmd = 0;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];
    ds0_t tmp_edit;
    ds_t buffer;
    sys_dsl3edit_tunnelv4_t* p_tunel_v4 = (sys_dsl3edit_tunnelv4_t*)&buffer;
    sys_dsl3edit_tunnelv6_t* p_tunel_v6 = (sys_dsl3edit_tunnelv6_t*)&buffer;

    if (sync)
    {
        p_wb_nh_info->info.ip_tunnel.flag =  p_nh_info->flag;
        p_wb_nh_info->info.ip_tunnel.l3ifid =  p_nh_info->l3ifid;
        p_wb_nh_info->info.ip_tunnel.gport =   p_nh_info->gport ;
        p_wb_nh_info->info.ip_tunnel.arp_id =   p_nh_info->arp_id;
        p_wb_nh_info->info.ip_tunnel.sa_index =  p_nh_info->sa_index ;
        p_wb_nh_info->info.ip_tunnel.dsl3edit_offset =  p_nh_info->dsl3edit_offset ;
        p_wb_nh_info->info.ip_tunnel.dest_vlan_ptr =  p_nh_info->dest_vlan_ptr ;
        p_wb_nh_info->info.ip_tunnel.span_id =  p_nh_info->span_id ;
        p_wb_nh_info->info.ip_tunnel.vn_id =  p_nh_info->vn_id ;
        p_wb_nh_info->info.ip_tunnel.dest_logic_port =  p_nh_info->dest_logic_port ;
        p_wb_nh_info->info.ip_tunnel.inner_l2_edit_offset =  p_nh_info->inner_l2_edit_offset ;
        p_wb_nh_info->info.ip_tunnel.outer_l2_edit_offset =  p_nh_info->outer_l2_edit_offset ;
        p_wb_nh_info->info.ip_tunnel.dot1ae_channel = p_nh_info->dot1ae_channel;
        p_wb_nh_info->info.ip_tunnel.sc_index = p_nh_info->sc_index;
        p_wb_nh_info->info.ip_tunnel.sci_en = p_nh_info->sci_en;
        p_wb_nh_info->info.ip_tunnel.dot1ae_en = p_nh_info->dot1ae_en;
        p_wb_nh_info->info.ip_tunnel.udf_profile_id = p_nh_info->udf_profile_id;
        p_wb_nh_info->info.ip_tunnel.is_12w = p_nh_info->is_12w;
        p_wb_nh_info->info.ip_tunnel.tunnel_type = p_nh_info->tunnel_type;
        p_wb_nh_info->info.ip_tunnel.inner_pkt_type = p_nh_info->inner_pkt_type;
        p_wb_nh_info->info.ip_tunnel.ctc_flag = p_nh_info->ctc_flag;
        p_wb_nh_info->info.ip_tunnel.inner_pkt_type = p_nh_info->inner_pkt_type;
        p_wb_nh_info->info.ip_tunnel.tunnel_type = p_nh_info->tunnel_type;
        p_wb_nh_info->info.ip_tunnel.share_type = p_nh_info->share_type;
        p_wb_nh_info->info.ip_tunnel.adjust_len = p_nh_info->adjust_len;
        p_wb_nh_info->info.ip_tunnel.rsv = 0;
    }
    else
    {
        p_nh_info->flag = p_wb_nh_info->info.ip_tunnel.flag;
        p_nh_info->l3ifid = p_wb_nh_info->info.ip_tunnel.l3ifid;
        p_nh_info->gport = p_wb_nh_info->info.ip_tunnel.gport;
        p_nh_info->arp_id = p_wb_nh_info->info.ip_tunnel.arp_id;
        p_nh_info->sa_index = p_wb_nh_info->info.ip_tunnel.sa_index;
        p_nh_info->dsl3edit_offset = p_wb_nh_info->info.ip_tunnel.dsl3edit_offset;
        p_nh_info->dest_vlan_ptr = p_wb_nh_info->info.ip_tunnel.dest_vlan_ptr;
        p_nh_info->span_id = p_wb_nh_info->info.ip_tunnel.span_id;
        p_nh_info->vn_id = p_wb_nh_info->info.ip_tunnel.vn_id;
        p_nh_info->dest_logic_port = p_wb_nh_info->info.ip_tunnel.dest_logic_port;
        p_nh_info->inner_l2_edit_offset = p_wb_nh_info->info.ip_tunnel.inner_l2_edit_offset;
        p_nh_info->outer_l2_edit_offset = p_wb_nh_info->info.ip_tunnel.outer_l2_edit_offset;
        p_nh_info->dot1ae_channel = p_wb_nh_info->info.ip_tunnel.dot1ae_channel;
        p_nh_info->sc_index = p_wb_nh_info->info.ip_tunnel.sc_index;
        p_nh_info->sci_en = p_wb_nh_info->info.ip_tunnel.sci_en;
        p_nh_info->dot1ae_en = p_wb_nh_info->info.ip_tunnel.dot1ae_en;
        p_nh_info->udf_profile_id = p_wb_nh_info->info.ip_tunnel.udf_profile_id;
        p_nh_info->is_12w = p_wb_nh_info->info.ip_tunnel.is_12w;
        p_nh_info->ctc_flag = p_wb_nh_info->info.ip_tunnel.ctc_flag;
        p_nh_info->inner_pkt_type = p_wb_nh_info->info.ip_tunnel.inner_pkt_type;
        p_nh_info->tunnel_type = p_wb_nh_info->info.ip_tunnel.tunnel_type;
        p_nh_info->share_type = p_wb_nh_info->info.ip_tunnel.share_type;
        p_nh_info->adjust_len = p_wb_nh_info->info.ip_tunnel.adjust_len;
        if (p_nh_info->udf_profile_id)
        {
            g_usw_nh_master[lchip]->udf_profile_ref_cnt[p_nh_info->udf_profile_id - 1]++;
        }

        if (p_nh_info->arp_id)
        {
            sys_nh_db_arp_t* p_arp = NULL;
            p_arp = (sys_usw_nh_lkup_arp_id(lchip, p_nh_info->arp_id));
            if (NULL == p_arp)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                return CTC_E_NOT_EXIST;
            }
            p_arp->ref_cnt++;
        }

        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV))
        {
            return CTC_E_NONE;
        }

        /*restore edit information*/
        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags , SYS_NH_INFO_FLAG_HAVE_L2EDI_3W))
        {
            entry_type = DRV_FROM_TMM(lchip) ? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W_RW : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W;
        }
        else if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags , SYS_NH_INFO_FLAG_HAVE_L2EDI_6W))
        {
            entry_type = DRV_FROM_TMM(lchip) ? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W_RW : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W;
        }
        else if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags , SYS_NH_INFO_FLAG_HAVE_SWAP_L2EDIT))
        {
            entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_SWAP;
        }

        if (p_nh_info->inner_l2_edit_offset)
        {
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type + SYS_NH_TYPE_STEP_TO_INNER, p_nh_info->inner_l2_edit_offset));
        }

        if (!p_nh_info->arp_id && !CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_LOOP_NH) && !(p_nh_info->hdr.nh_entry_flags & SYS_NH_INFO_FLAG_USE_ECMP_IF)
            && p_nh_info->outer_l2_edit_offset)
        {
            entry_type = CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_L2EDIT8W)?SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W:SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W;
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_nh_info->outer_l2_edit_offset));
        }

        if (p_nh_info->dsl3edit_offset)
        {

            if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_IN_V6))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6;

            }
            else if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_NAT_V4))
            {
                if(CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_NAT64))
                {
                    entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4;
                }
                else if(CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_NAT_MASK))
                {
                    entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_NAT_8W;
                }
                else
                {
                    entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_NAT_4W;
                }
            }
            else if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_NAT_V6))
            {
                if(CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_NAT64))
                {
                    entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6;
                }
                else if(CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_NAT_MASK))
                {
                    entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_NAT_V6_16W;
                }
                else
                {
                    entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_NAT_V6_8W;
                }
            }
            else if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_IVI_6TO4))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_NAT_4W;

            }
            else if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_IVI_4TO6))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_NAT_8W;

            }
            else if (p_nh_info->is_12w)
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4_4X;

            }
            else
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4;
            }
            if (((SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6 == entry_type)
                 || (SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4_4X == entry_type)
                 || (SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4 == entry_type))
                && (0 == p_nh_info->inner_l2_edit_offset)
                && (!CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_NAT64)))
            {
                entry_type += SYS_NH_TYPE_STEP_TO_INNER;
            }

            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit2(lchip, entry_type, p_nh_info->dsl3edit_offset, tmp_edit));
        }

        is_vxlan_v6 = (p_nh_info->share_type == SYS_NH_L3EDIT_TUNNELV6_SHARE_TYPE_VXLAN) ? 1:0;
        if((DRV_FROM_TMM(lchip) && (p_nh_info->share_type == SYS_NH_L3EDIT_TUNNELV6_SHARE_TYPE_VXLAN || p_nh_info->share_type == SYS_NH_L3EDIT_TUNNELV4_SHARE_TYPE_VXLAN))
            || (DRV_IS_TSINGMA(lchip) && (p_nh_info->tunnel_type == CTC_TUNNEL_TYPE_VXLAN_IN6 || p_nh_info->tunnel_type == CTC_TUNNEL_TYPE_VXLAN_IN4)
               && !CTC_FLAG_ISSET(p_nh_info->flag, CTC_IP_NH_TUNNEL_FLAG_OVERLAY_VXLAN_GPE)))
        {
            sal_memset(&buffer, 0, sizeof(buffer));
            if(is_vxlan_v6)
            {
                p_tunel_v6->share_type = p_nh_info->share_type;
            }
            else
            {
                p_tunel_v4->share_type = p_nh_info->share_type;
            }

            if (p_nh_master->nh_table_info_array[entry_type].p_func_unmap)
            {
                CTC_ERROR_RETURN((*p_nh_master->nh_table_info_array[entry_type].p_func_unmap)(lchip, &buffer, &tmp_edit));
            }

            p_nh_info->vxlan_edit_idx = is_vxlan_v6 ? p_tunel_v6->vxlan_edit_idx : p_tunel_v4->vxlan_edit_idx;
            if(p_nh_info->vxlan_edit_idx)
            {
                g_usw_nh_master[lchip]->vxlan_edit_profile[p_nh_info->vxlan_edit_idx].ref_cnt++;
            }
        }

        if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_IN_V4)
            && CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_HAVE_IPSA))
        {
            sys_nh_ip_tunnel_sa_v4_node_t* p_node = NULL;
            DsL3TunnelV4IpSa_m v4_sa;
            p_node = (sys_nh_ip_tunnel_sa_v4_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_4] + p_nh_info->sa_index;
            cmd = DRV_IOR(DsL3TunnelV4IpSa_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_info->sa_index, cmd, &v4_sa));
            p_node->ipv4 = GetDsL3TunnelV4IpSa(V, ipSa_f, &v4_sa);
            p_node->count++;
            if (p_node->count == 1)
            {
                g_usw_nh_master[lchip]->nhtbl_used_cnt[SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4_IPSA]++;
            }
        }

        if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_FLAG_IN_V6)
            && CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_IP_TUNNEL_HAVE_IPSA))
        {
            sys_nh_ip_tunnel_sa_v6_node_t* p_node = NULL;
            DsL3TunnelV6IpSa_m v6_sa;
            ipv6_addr_t hw_ipv6_address;
            p_node = (sys_nh_ip_tunnel_sa_v6_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_6] + p_nh_info->sa_index;
            cmd = DRV_IOR(DsL3TunnelV6IpSa_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_info->sa_index, cmd, &v6_sa));
            GetDsL3TunnelV6IpSa(A, ipSa_f, &v6_sa, hw_ipv6_address);
            p_node->ipv6[0] = (hw_ipv6_address[3]);
            p_node->ipv6[1] = (hw_ipv6_address[2]);
            p_node->ipv6[2] = (hw_ipv6_address[1]);
            p_node->ipv6[3] = (hw_ipv6_address[0]);
            p_node->count++;
            if (p_node->count == 1)
            {
                g_usw_nh_master[lchip]->nhtbl_used_cnt[SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6_IPSA]++;
            }
        }

        /*add to overlay tunnel db*/
        if(g_usw_nh_master[lchip]->bind_ldp && p_nh_info->dest_logic_port && (
            p_nh_info->tunnel_type == CTC_TUNNEL_TYPE_VXLAN_IN4 ||
            p_nh_info->tunnel_type == CTC_TUNNEL_TYPE_VXLAN_IN6))
        {
            CTC_ERROR_RETURN(_sys_usw_nh_ip_tunnel_add_to_tunnel_db(lchip, p_nh_info));
            p_nh_info->bind_ldp = 1;
        }

        if (g_usw_nh_master[lchip]->bind_ldp && DRV_IS_TSINGMA(lchip))
        {
            CTC_ERROR_RETURN(sys_usw_nh_update_offset_ref_cnt(lchip, p_nh_info->hdr.nh_id , 1));
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_wlan_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_wlan_tunnel_t  *p_nh_info = (sys_nh_info_wlan_tunnel_t  *)p_nh_info_com;
    uint8 entry_type = 0;
    uint32 cmd = 0;

    if (sync)
    {
        p_wb_nh_info->info.wlan.flag =  p_nh_info->flag;
        p_wb_nh_info->info.wlan.dsl3edit_offset =  p_nh_info->dsl3edit_offset;
        p_wb_nh_info->info.wlan.gport =   p_nh_info->gport ;
        p_wb_nh_info->info.wlan.sa_index =   p_nh_info->sa_index;
        p_wb_nh_info->info.wlan.dest_vlan_ptr =  p_nh_info->dest_vlan_ptr;
        p_wb_nh_info->info.wlan.inner_l2_ptr =  p_nh_info->inner_l2_ptr ;
    }
    else
    {
        p_nh_info->flag = p_wb_nh_info->info.wlan.flag;
        p_nh_info->dsl3edit_offset = p_wb_nh_info->info.wlan.dsl3edit_offset;
        p_nh_info->gport = p_wb_nh_info->info.wlan.gport;
        p_nh_info->sa_index = p_wb_nh_info->info.wlan.sa_index;
        p_nh_info->dest_vlan_ptr = p_wb_nh_info->info.wlan.dest_vlan_ptr;
        p_nh_info->inner_l2_ptr = p_wb_nh_info->info.wlan.inner_l2_ptr;

        if (!p_nh_info->use_multi_l2_ptr)
        {
            if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags , SYS_NH_INFO_FLAG_HAVE_L2EDI_6W))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W;
            }
            else if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags , SYS_NH_INFO_FLAG_HAVE_L2EDI_3W))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W;
            }

            if (p_nh_info->inner_l2_ptr)
            {
                CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_nh_info->inner_l2_ptr));
            }
        }

        if (p_nh_info->dsl3edit_offset)
        {
            if (CTC_FLAG_ISSET(p_nh_info->flag , SYS_NH_WLAN_TUNNEL_FLAG_IN_V4))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4;
            }
            else if (CTC_FLAG_ISSET(p_nh_info->flag , SYS_NH_WLAN_TUNNEL_FLAG_IN_V6))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6;
            }
            if (p_nh_info->dsl3edit_offset)
            {
                CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_nh_info->dsl3edit_offset));
            }
        }

        if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_WLAN_TUNNEL_FLAG_IN_V4)
            &&CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_WLAN_TUNNEL_HAVE_IPSA) )
        {
            sys_nh_ip_tunnel_sa_v4_node_t* p_node = NULL;
            DsL3TunnelV4IpSa_m v4_sa;
            p_node = (sys_nh_ip_tunnel_sa_v4_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_4] + p_nh_info->sa_index;
            cmd = DRV_IOR(DsL3TunnelV4IpSa_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_info->sa_index, cmd, &v4_sa));
            p_node->ipv4 = GetDsL3TunnelV4IpSa(V, ipSa_f, &v4_sa);
            p_node->count++;
            if (p_node->count == 1)
            {
                g_usw_nh_master[lchip]->nhtbl_used_cnt[SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4_IPSA]++;
            }
        }

        if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_WLAN_TUNNEL_FLAG_IN_V6)
            &&CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_WLAN_TUNNEL_HAVE_IPSA) )
        {
            sys_nh_ip_tunnel_sa_v6_node_t* p_node = NULL;
            DsL3TunnelV6IpSa_m v6_sa;
            ipv6_addr_t hw_ipv6_address;
            p_node = (sys_nh_ip_tunnel_sa_v6_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_6] + p_nh_info->sa_index;
            cmd = DRV_IOR(DsL3TunnelV6IpSa_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_info->sa_index, cmd, &v6_sa));
            GetDsL3TunnelV6IpSa(A, ipSa_f, &v6_sa, hw_ipv6_address);
            p_node->ipv6[0] = (hw_ipv6_address[3]);
            p_node->ipv6[1] = (hw_ipv6_address[2]);
            p_node->ipv6[2] = (hw_ipv6_address[1]);
            p_node->ipv6[3] = (hw_ipv6_address[0]);

            p_node->count++;
            if (p_node->count == 1)
            {
                g_usw_nh_master[lchip]->nhtbl_used_cnt[SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6_IPSA]++;
            }
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_srv6_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_srv6_t  *p_nh_info = (sys_nh_info_srv6_t  *)p_nh_info_com;

    if (sync)
    {
        p_wb_nh_info->info.srv6.l3ifid                   = p_nh_info->l3ifid;
        p_wb_nh_info->info.srv6.flag                     = p_nh_info->flag;
        p_wb_nh_info->info.srv6.dest_logic_port          = p_nh_info->dest_logic_port;
        p_wb_nh_info->info.srv6.srh_id                   = p_nh_info->srh_id;
        p_wb_nh_info->info.srv6.gport                    = p_nh_info->gport;
        p_wb_nh_info->info.srv6.dsl3edit_offset          = p_nh_info->dsl3edit_offset;
        p_wb_nh_info->info.srv6.outer_l2_edit_offset     = p_nh_info->outer_l2_edit_offset;
        p_wb_nh_info->info.srv6.srv6_type                = p_nh_info->srv6_type;
        p_wb_nh_info->info.srv6.svlan_edit_type          = p_nh_info->svlan_edit_type;
        p_wb_nh_info->info.srv6.cvlan_edit_type          = p_nh_info->cvlan_edit_type;
        p_wb_nh_info->info.srv6.rsv                      = 0;
        p_wb_nh_info->info.srv6.ipsa_index               = p_nh_info->ipsa_index;
        p_wb_nh_info->info.srv6.aps_xcon_met             = p_nh_info->aps_xcon_met;
        p_wb_nh_info->info.srv6.met_offset             = p_nh_info->met_offset;
        p_wb_nh_info->info.srv6.replace_last             = p_nh_info->replace_last;
        p_wb_nh_info->info.srv6.fp_id                    = p_nh_info->fp_id;
        p_wb_nh_info->info.srv6.ecmp_if_id               = p_nh_info->ecmp_if_id;
        p_wb_nh_info->info.srv6.rsv1                     = 0;
    }
    else
    {
        sys_nh_db_srh_t    *p_srh_tnl = NULL;

        p_nh_info->l3ifid                   = p_wb_nh_info->info.srv6.l3ifid;
        p_nh_info->flag                     = p_wb_nh_info->info.srv6.flag;
        p_nh_info->dest_logic_port          = p_wb_nh_info->info.srv6.dest_logic_port;
        p_nh_info->gport                    = p_wb_nh_info->info.srv6.gport;
        p_nh_info->dsl3edit_offset          = p_wb_nh_info->info.srv6.dsl3edit_offset;
        p_nh_info->outer_l2_edit_offset     = p_wb_nh_info->info.srv6.outer_l2_edit_offset;

        p_nh_info->srv6_type                = p_wb_nh_info->info.srv6.srv6_type;
        p_nh_info->svlan_edit_type          = p_wb_nh_info->info.srv6.svlan_edit_type;
        p_nh_info->cvlan_edit_type          = p_wb_nh_info->info.srv6.cvlan_edit_type;
        p_nh_info->ipsa_index               = p_wb_nh_info->info.srv6.ipsa_index;
        p_nh_info->aps_xcon_met             = p_wb_nh_info->info.srv6.aps_xcon_met;
        p_nh_info->met_offset               = p_wb_nh_info->info.srv6.met_offset;
        p_nh_info->srh_id                   = p_wb_nh_info->info.srv6.srh_id;
        p_nh_info->replace_last             = p_wb_nh_info->info.srv6.replace_last;
        p_nh_info->fp_id                    = p_wb_nh_info->info.srv6.fp_id;
        p_nh_info->ecmp_if_id          = p_wb_nh_info->info.srv6.ecmp_if_id;
        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV))
        {
            return CTC_E_NONE;
        }

        if (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_SRV6_FLAG_HAVE_IPSA))
        {
            sys_nh_ip_tunnel_sa_v6_node_t* p_node = NULL;
            DsL3TunnelV6IpSa_m v6_sa;
            uint32 cmd = 0;
            ipv6_addr_t hw_ipv6_address;

            p_node = (sys_nh_ip_tunnel_sa_v6_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_6] + p_nh_info->ipsa_index;
            cmd = DRV_IOR(DsL3TunnelV6IpSa_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nh_info->ipsa_index, cmd, &v6_sa));

            sal_memset(&hw_ipv6_address, 0, sizeof(ipv6_addr_t));
            GetDsL3TunnelV6IpSa(A, ipSa_f, &v6_sa, hw_ipv6_address);
            p_node->ipv6[0] = (hw_ipv6_address[3]);
            p_node->ipv6[1] = (hw_ipv6_address[2]);
            p_node->ipv6[2] = (hw_ipv6_address[1]);
            p_node->ipv6[3] = (hw_ipv6_address[0]);
            p_node->count++;
            if (p_node->count == 1)
            {
                g_usw_nh_master[lchip]->nhtbl_used_cnt[SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6_IPSA]++;
            }
        }

        if (0 == p_nh_info->ecmp_if_id)
        {
            p_srh_tnl = _sys_usw_nh_lkup_srh_id(lchip, p_nh_info->srh_id);
            CTC_ERROR_RETURN(_sys_usw_nh_srv6_update_tnl_mem(lchip, (sys_nh_info_com_t*)p_nh_info, p_srh_tnl, 1));
        }
        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L3EDIT) && p_nh_info->dsl3edit_offset)
        {
            if ((p_srh_tnl && !p_srh_tnl->num && !CTC_FLAG_ISSET(p_srh_tnl->flag, SYS_NH_SRH_FLAG_APS)) || ((0 != p_nh_info->ecmp_if_id) && !CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_SRV6_FLAG_SRH_IS_LDP)))
            {
                CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6, p_nh_info->dsl3edit_offset));
            }
            else if (p_nh_info->dsl3edit_offset)
            {
                sys_usw_nh_offset_alloc_from_position(lchip,
                        (CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_SRV6_FLAG_ENCAP))? SYS_NH_ENTRY_TYPE_L3EDIT_ADD_SRV6 : SYS_NH_ENTRY_TYPE_L3EDIT_RW_SRV6,
                        1, p_nh_info->dsl3edit_offset);
            }
        }

        if (!CTC_FLAG_ISSET(p_nh_info->flag, SYS_NH_SRV6_FLAG_LOOP_NH) && p_srh_tnl && !p_srh_tnl->arp_id)
        {
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, p_nh_info->outer_l2_edit_offset));
        }

        if (p_nh_info->aps_xcon_met && (0 != p_nh_info->met_offset))
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_MET, 1, p_nh_info->met_offset);
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_ol_vni_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_ol_vni_t  *p_nh_info = (sys_nh_info_ol_vni_t  *)p_nh_info_com;
    if (sync)
    {
        p_wb_nh_info->info.ol_vni.inner_l2_edit_offset = p_nh_info->inner_l2_edit_offset;
        p_wb_nh_info->info.ol_vni.cvlan_edit_type = p_nh_info->cvlan_edit_type;
        p_wb_nh_info->info.ol_vni.svlan_edit_type = p_nh_info->svlan_edit_type;
    }
    else
    {
        p_nh_info->inner_l2_edit_offset = p_wb_nh_info->info.ol_vni.inner_l2_edit_offset;
        p_nh_info->cvlan_edit_type = p_wb_nh_info->info.ol_vni.cvlan_edit_type;
        p_nh_info->svlan_edit_type = p_wb_nh_info->info.ol_vni.svlan_edit_type;
        if (p_nh_info->inner_l2_edit_offset)
        {
            uint8 entry_type = 0;
            if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags , SYS_NH_INFO_FLAG_HAVE_L2EDI_3W))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W_RW + SYS_NH_TYPE_STEP_TO_INNER;
            }
            else if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags , SYS_NH_INFO_FLAG_HAVE_L2EDI_6W))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W_RW + SYS_NH_TYPE_STEP_TO_INNER;
            }
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_nh_info->inner_l2_edit_offset));
        }
        g_usw_nh_master[lchip]->overlay_ovi_num++;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_overlay_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_overlay_t  *p_nh_info = (sys_nh_info_overlay_t  *)p_nh_info_com;
    if (sync)
    {
        p_wb_nh_info->info.overlay.gport = p_nh_info->gport;
        p_wb_nh_info->info.overlay.nhid = p_nh_info->nhid;
        p_wb_nh_info->info.overlay.dest_logic_port = p_nh_info->dest_logic_port;
        p_wb_nh_info->info.overlay.ecmp_gid = p_nh_info->ecmp_gid;
		p_wb_nh_info->info.overlay.is_ecmp_nh = p_nh_info->is_ecmp_nh;
    }
    else
    {
        p_nh_info->gport = p_wb_nh_info->info.overlay.gport;
        p_nh_info->nhid = p_wb_nh_info->info.overlay.nhid;
        p_nh_info->dest_logic_port = p_wb_nh_info->info.overlay.dest_logic_port;
        p_nh_info->ecmp_gid = p_wb_nh_info->info.overlay.ecmp_gid;
		p_nh_info->is_ecmp_nh = p_wb_nh_info->info.overlay.is_ecmp_nh;

        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_PORT))
        {
            sys_nh_db_ol_tunnel_t *tunnel_db = NULL;
            tunnel_db = _sys_usw_nh_lkup_tunnel(lchip, p_nh_info->dest_logic_port);

            if (NULL == tunnel_db)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " [Nexthop] overlay tunnel not exist!\n");
                return CTC_E_NOT_EXIST;
            }
            _sys_usw_nh_update_ol_tunnel_ref_info(lchip, (sys_nh_info_com_t*)p_nh_info, tunnel_db, 1);
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_srh(uint8 lchip, sys_nh_db_srh_t* p_db, sys_wb_nh_srh_t *p_wb, uint8 sync)
{
    if (sync)
    {
        p_wb->srh_id                 =  p_db->srh_id ;
        p_wb->l3edit_ptr            =  p_db->l3edit_ptr;
        p_wb->is_reduce         =  p_db->is_reduce;
        p_wb->segment_left           =  p_db->segment_left;
        p_wb->num           =  p_db->num ;
        p_wb->alloc_en           =  p_db->alloc_en ;
        p_wb->arp_id           =  p_db->arp_id ;
        p_wb->flag                 =  p_db->flag ;
        p_wb->p_srh_id                 =  p_db->p_srh_id ;
        p_wb->ldp                 =  p_db->ldp ;
        p_wb->rsv             = 0;
        p_wb->rsv1            = 0;
    }
    else
    {
        p_db->srh_id                 =  p_wb->srh_id ;
        p_db->l3edit_ptr            =  p_wb->l3edit_ptr;
        p_db->is_reduce         =  p_wb->is_reduce;
        p_db->segment_left           =  p_wb->segment_left;
        p_db->num           =  p_wb->num;
        p_db->alloc_en           =  p_wb->alloc_en;
        p_db->arp_id           =  p_wb->arp_id;
        p_db->flag           =  p_wb->flag;
        p_db->p_srh_id           =  p_wb->p_srh_id;
        p_db->ldp                 =  p_wb->ldp;
        if (p_db->l3edit_ptr && !CTC_FLAG_ISSET(p_db->flag, SYS_NH_SRH_FLAG_APS))
        {
            sys_usw_nh_offset_alloc_from_position(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), SYS_NH_ENTRY_TYPE_L3EDIT_SRH + SYS_NH_TYPE_STEP_TO_INNER, 1, p_db->l3edit_ptr);
        }

        if (p_db->arp_id)
        {
            sys_nh_db_arp_t* p_arp = NULL;
            p_arp = (sys_usw_nh_lkup_arp_id(lchip, p_db->arp_id));
            if (NULL == p_arp)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                return CTC_E_NOT_EXIST;
            }
            p_arp->ref_cnt++;
        }

    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_ol_tunnel(uint8 lchip, sys_nh_db_ol_tunnel_t* p_db, sys_wb_nh_ol_tunnel_t *p_wb, uint8 sync)
{
    uint8  entry_type = 0;
    uint32 cmd        = 0;
    if (sync)
    {
        p_wb->logic_port                 =  p_db->logic_port ;
        p_wb->dsl3edit_offset            =  p_db->dsl3edit_offset;
        p_wb->sa_index               =  p_db->sa_index ;
        p_wb->flag         =  p_db->flag;
        p_wb->arp_id           =  p_db->arp_id;
        p_wb->dot1ae_channel           =  p_db->dot1ae_channel;
        p_wb->sc_index           =  p_db->sc_index;
        p_wb->dot1ae_en           =  p_db->dot1ae_en;
        p_wb->sci_en           =  p_db->sci_en;
        p_wb->is_4x           =  p_db->is_4x;
        p_wb->rsv              =    0;
        p_wb->ecmp_if_id      =  p_db->ecmp_if_id;
        p_wb->tunnel_type     =  p_db->tunnel_type;
        p_wb->ul_nhid           = p_db->ul_nhid;
        p_wb->ul_nh_en           = p_db->ul_nh_en;
        p_wb->gport           = p_db->gport;

    }
    else
    {
        p_db->logic_port                 =  p_wb->logic_port ;
        p_db->dsl3edit_offset            =  p_wb->dsl3edit_offset;
        p_db->sa_index               =  p_wb->sa_index ;
        p_db->flag         =  p_wb->flag;
        p_db->arp_id           =  p_wb->arp_id;
        p_db->dot1ae_channel           =  p_wb->dot1ae_channel;
        p_db->sc_index           =  p_wb->sc_index;
        p_db->dot1ae_en           =  p_wb->dot1ae_en;
        p_db->sci_en           =  p_wb->sci_en;
        p_db->is_4x           =  p_wb->is_4x;
        p_db->ecmp_if_id      = p_wb->ecmp_if_id;
        p_db->tunnel_type     = p_wb->tunnel_type;
        p_db->ul_nhid           = p_wb->ul_nhid;
        p_db->ul_nh_en           = p_wb->ul_nh_en;
        p_db->gport           = p_wb->gport;

        if (p_db->dsl3edit_offset)
        {
            uint8 inner_header_type = 0;
            ds0_t tmp_edit;
            if (CTC_FLAG_ISSET(p_db->flag, SYS_NH_OL_TUNNEL_FLAG_IN_V6))
            {
                entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6;

            }
            else if (CTC_FLAG_ISSET(p_db->flag, SYS_NH_OL_TUNNEL_FLAG_IN_V4))
            {
                entry_type = p_db->is_4x? SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4_4X : SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4;
            }

            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit2(lchip, entry_type, p_db->dsl3edit_offset, tmp_edit));
            inner_header_type = (CTC_FLAG_ISSET(p_db->flag, SYS_NH_OL_TUNNEL_FLAG_IN_V6)) ? \
                            GetDsL3EditAddIp6(V, l4EditType_f, tmp_edit): GetDsL3EditAddIp4(V, l4EditType_f, tmp_edit);
            /*vxlan tunnel*/
            if(2 == inner_header_type)
            {
                p_db->vxlan_edit_idx = (CTC_FLAG_ISSET(p_db->flag, SYS_NH_OL_TUNNEL_FLAG_IN_V6))? \
                    GetDsL3EditAddIp6(V, vxlanFamilyId_f, tmp_edit): GetDsL3EditAddIp4(V, vxlanFamilyId_f, tmp_edit);
                if(p_db->vxlan_edit_idx)
                {
                    g_usw_nh_master[lchip]->vxlan_edit_profile[p_db->vxlan_edit_idx].ref_cnt++;
                }
            }
        }

        if (CTC_FLAG_ISSET(p_db->flag, SYS_NH_OL_TUNNEL_FLAG_IN_V6)
            && CTC_FLAG_ISSET(p_db->flag, SYS_NH_OL_TUNNEL_HAVE_IPSA))
        {
            sys_nh_ip_tunnel_sa_v6_node_t* p_node = NULL;
            DsL3TunnelV6IpSa_m v6_sa;
            ipv6_addr_t hw_ipv6_address;
            p_node = (sys_nh_ip_tunnel_sa_v6_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_6] + p_db->sa_index;
            cmd = DRV_IOR(DsL3TunnelV6IpSa_t, DRV_ENTRY_FLAG);
            CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_db->sa_index, cmd, &v6_sa));
            GetDsL3TunnelV6IpSa(A, ipSa_f, &v6_sa, hw_ipv6_address);
            p_node->ipv6[0] = (hw_ipv6_address[3]);
            p_node->ipv6[1] = (hw_ipv6_address[2]);
            p_node->ipv6[2] = (hw_ipv6_address[1]);
            p_node->ipv6[3] = (hw_ipv6_address[0]);
            p_node->count++;
            if (p_node->count == 1)
            {
                g_usw_nh_master[lchip]->nhtbl_used_cnt[SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V6_IPSA]++;
            }
        }

        if (p_db->arp_id && p_db->ul_nh_en == 0)
        {
            sys_nh_db_arp_t* p_arp = NULL;
            p_arp = (sys_usw_nh_lkup_arp_id(lchip, p_db->arp_id));
            if (NULL == p_arp)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                return CTC_E_NOT_EXIST;
            }
            p_arp->ref_cnt++;
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_arp(uint8 lchip, sys_nh_db_arp_t* p_db_arp, sys_wb_nh_arp_t *p_wb_arp, uint8 sync)
{
    if (sync)
    {
        sal_memcpy(&p_wb_arp->mac_da, &p_db_arp->mac_da, sizeof(mac_addr_t));
        p_wb_arp->flag                 =  p_db_arp->flag ;
        p_wb_arp->l3if_type            =  p_db_arp->l3if_type;
        p_wb_arp->offset               =  p_db_arp->offset ;
        p_wb_arp->offset_dyn           =  p_db_arp->offset_dyn;
        p_wb_arp->output_vid           =  p_db_arp->output_vid ;
        p_wb_arp->output_vlan_is_svlan =  p_db_arp->output_vlan_is_svlan;
        p_wb_arp->gport                =  p_db_arp->gport ;
        p_wb_arp->destmap_profile      =  p_db_arp->destmap_profile;
        p_wb_arp->arp_id               =  p_db_arp->arp_id;
        p_wb_arp->l3if_id              =  p_db_arp->l3if_id;
        p_wb_arp->output_cvid          =  p_db_arp->output_cvid;
        p_wb_arp->is_8w                =  p_db_arp->is_8w;
        p_wb_arp->rsv                  =   0;
        p_wb_arp->rsv1                 =   0;
        p_wb_arp->ldp_mac_profile      =  p_db_arp->ldp_mac_profile;
        p_wb_arp->dsfwd_offset         =  p_db_arp->dsfwd_offset;
    }
    else
    {
        sal_memcpy(&p_db_arp->mac_da, &p_wb_arp->mac_da, sizeof(mac_addr_t));
        p_db_arp->flag                 = p_wb_arp->flag;
        p_db_arp->l3if_type            = p_wb_arp->l3if_type ;
        p_db_arp->offset               = p_wb_arp->offset ;
        p_db_arp->offset_dyn           = p_wb_arp->offset_dyn ;
        p_db_arp->output_vid           = p_wb_arp->output_vid ;
        p_db_arp->output_vlan_is_svlan = p_wb_arp->output_vlan_is_svlan;
        p_db_arp->gport                = p_wb_arp->gport;
        p_db_arp->destmap_profile      = p_wb_arp->destmap_profile;
        p_db_arp->arp_id               = p_wb_arp->arp_id;
        p_db_arp->l3if_id              = p_wb_arp->l3if_id;
        p_db_arp->output_cvid          = p_wb_arp->output_cvid;
        p_db_arp->is_8w                = p_wb_arp->is_8w;
        p_db_arp->ldp_mac_profile      = p_wb_arp->ldp_mac_profile;
        p_db_arp->dsfwd_offset         = p_wb_arp->dsfwd_offset;

        if (p_db_arp->offset_dyn)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, p_db_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W : SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, 1, p_db_arp->offset_dyn);
        }

        if (p_db_arp->offset)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, p_db_arp->is_8w? SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W : SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, p_db_arp->offset);
        }




        if(p_db_arp->destmap_profile)
        {
            /*recover opf*/
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_DESTMAP_PROFILE, 1, p_db_arp->destmap_profile);
        }

        if(p_db_arp->ldp_mac_profile)
        {
            /*recover opf*/
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_LDP_MAC_PROFILE, 1, p_db_arp->ldp_mac_profile);
        }

        if(p_db_arp->dsfwd_offset)
        {
            /*recover opf*/
            sys_usw_nh_offset_alloc_from_position(lchip, DRV_FROM_AT(lchip)? SYS_NH_ENTRY_TYPE_FWD_HALF1 : SYS_NH_ENTRY_TYPE_FWD_HALF, 1, p_db_arp->dsfwd_offset);
        }

        p_db_arp->pd = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_arp_pdata_t));
        if (NULL == p_db_arp->pd)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_db_arp->pd, 0, sizeof(sys_nh_db_arp_pdata_t));
        p_db_arp->pd->nh_list = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(ctc_list_pointer_t));
        if (NULL == p_db_arp->pd->nh_list)
        {
            mem_free(p_db_arp->pd);
            return CTC_E_NO_MEMORY;
        }
        ctc_list_pointer_init(p_db_arp->pd->nh_list);
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_mpls_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info,
        uint8 sync)
{
    sys_nh_info_mpls_t  *p_nh_info = (sys_nh_info_mpls_t*)p_nh_info_com;
    int32 ret = 0;

    uint8 entry_type = 0;

    if (sync)
    {
        p_wb_nh_info->info.mpls.gport = p_nh_info->gport;
        p_wb_nh_info->info.mpls.l3ifid = p_nh_info->l3ifid;
        p_wb_nh_info->info.mpls.dest_logic_port = p_nh_info->dest_logic_port;
        p_wb_nh_info->info.mpls.service_id = p_nh_info->service_id;

        p_wb_nh_info->info.mpls.cw_index = p_nh_info->cw_index;
        p_wb_nh_info->info.mpls.arp_id = p_nh_info->arp_id;
        p_wb_nh_info->info.mpls.outer_l2_ptr = p_nh_info->outer_l2_ptr;

        p_wb_nh_info->info.mpls.aps_xcon_met =  p_nh_info->aps_xcon_met;
        p_wb_nh_info->info.mpls.met_offset =  p_nh_info->met_offset;
        p_wb_nh_info->info.mpls.nh_prop =  p_nh_info->nh_prop;
        p_wb_nh_info->info.mpls.op_code =  p_nh_info->op_code;
        p_wb_nh_info->info.mpls.ttl_mode =  p_nh_info->ttl_mode;
        p_wb_nh_info->info.mpls.is_hvpls =  p_nh_info->is_hvpls;


        p_wb_nh_info->info.mpls.inner_l2_ptr = p_nh_info->inner_l2_ptr;
        p_wb_nh_info->info.mpls.dsl3edit_offset = p_nh_info->dsl3edit_offset;
        p_wb_nh_info->info.mpls.is_loop_nh =  p_nh_info->is_loop_nh;
        p_wb_nh_info->info.mpls.svlan_edit_type =  p_nh_info->svlan_edit_type;
        p_wb_nh_info->info.mpls.cvlan_edit_type =  p_nh_info->cvlan_edit_type;
        p_wb_nh_info->info.mpls.ttl =  p_nh_info->ttl;
        p_wb_nh_info->info.mpls.rsv =  0;
        p_wb_nh_info->info.mpls.tunnel_id = p_nh_info->tunnel_id;
        p_wb_nh_info->info.mpls.adjust_len = p_nh_info->adjust_len;
    }
    else
    {
        sys_nh_db_mpls_tunnel_t* p_mpls_tunnel = NULL;

        p_nh_info->gport = p_wb_nh_info->info.mpls.gport;
        p_nh_info->l3ifid = p_wb_nh_info->info.mpls.l3ifid;
        p_nh_info->dest_logic_port = p_wb_nh_info->info.mpls.dest_logic_port;
        p_nh_info->service_id = p_wb_nh_info->info.mpls.service_id;
        p_nh_info->cw_index = p_wb_nh_info->info.mpls.cw_index;
        p_nh_info->arp_id = p_wb_nh_info->info.mpls.arp_id;
        p_nh_info->outer_l2_ptr = p_wb_nh_info->info.mpls.outer_l2_ptr;

        p_nh_info->aps_xcon_met = p_wb_nh_info->info.mpls.aps_xcon_met;
        p_nh_info->met_offset = p_wb_nh_info->info.mpls.met_offset;
        p_nh_info->adjust_len = p_wb_nh_info->info.mpls.adjust_len;
        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L3EDIT)&&p_wb_nh_info->info.mpls.dsl3edit_offset)
        {
            entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_MPLS;
            if ((0 == p_wb_nh_info->info.mpls.inner_l2_ptr) || p_wb_nh_info->info.mpls.is_loop_nh)
            {
                entry_type += SYS_NH_TYPE_STEP_TO_INNER;
            }
			if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_APS) || MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_OAM))
		    {
		        CTC_ERROR_RETURN(sys_usw_nh_offset_alloc_from_position(lchip, entry_type, 1, p_wb_nh_info->info.mpls.dsl3edit_offset));
			}
			else
			{
            	CTC_ERROR_RETURN(sys_usw_nh_wb_restore_edit(lchip, entry_type, p_wb_nh_info->info.mpls.dsl3edit_offset));
			}
        }

        p_nh_info->inner_l2_ptr = p_wb_nh_info->info.mpls.inner_l2_ptr;
        p_nh_info->dsl3edit_offset = p_wb_nh_info->info.mpls.dsl3edit_offset;
        p_nh_info->svlan_edit_type = p_wb_nh_info->info.mpls.svlan_edit_type;
        p_nh_info->cvlan_edit_type = p_wb_nh_info->info.mpls.cvlan_edit_type;
        p_nh_info->is_loop_nh = p_wb_nh_info->info.mpls.is_loop_nh;
        p_nh_info->ttl = p_wb_nh_info->info.mpls.ttl;
        p_nh_info->svlan_edit_type = p_wb_nh_info->info.mpls.svlan_edit_type;
        p_nh_info->cvlan_edit_type = p_wb_nh_info->info.mpls.cvlan_edit_type;

        p_nh_info->pd = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_info_mpls_pdata_t));
        if (NULL == p_nh_info->pd)
        {
            return CTC_E_NO_MEMORY;
        }
        sal_memset(p_nh_info->pd, 0, sizeof(sys_nh_info_mpls_pdata_t));

        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_IS_UNROV))
        {
            return CTC_E_NONE;
        }

        /*restore mpls tunnel id*/
        CTC_ERROR_RETURN(sys_usw_nh_lkup_mpls_tunnel(lchip, p_wb_nh_info->info.mpls.tunnel_id, &p_mpls_tunnel));
        p_nh_info->tunnel_id = p_wb_nh_info->info.mpls.tunnel_id;
        if (p_mpls_tunnel)
        {
            sys_nh_ref_list_node_t* p_nh_ref_list_node = NULL;
            p_nh_ref_list_node = (sys_nh_ref_list_node_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_ref_list_node_t));
            if (p_nh_ref_list_node == NULL)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
                return CTC_E_NO_MEMORY;
            }
            p_nh_ref_list_node->p_ref_nhinfo = (sys_nh_info_com_t* )p_nh_info;
            p_nh_ref_list_node->p_next = p_mpls_tunnel->pd->p_ref_nh_list;

            p_mpls_tunnel->pd->p_ref_nh_list = p_nh_ref_list_node;
            p_nh_info->tunnel_id_valid =1;
        }

        /*restore edit information*/
        if ( p_wb_nh_info->info.mpls.inner_l2_ptr  && !p_wb_nh_info->info.mpls.is_loop_nh)
        {
            entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_INNER_6W + SYS_NH_TYPE_STEP_TO_INNER;
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_wb_nh_info->info.mpls.inner_l2_ptr));
        }
        else if (p_wb_nh_info->info.mpls.outer_l2_ptr)
        {
            entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W;
            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_wb_nh_info->info.mpls.outer_l2_ptr));
        }

        if (p_nh_info->aps_xcon_met && (0 != p_nh_info->met_offset))
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_MET, 1, p_nh_info->met_offset);
        }
    }

    return ret;

}

STATIC int32
_sys_usw_nh_wb_mapping_mpls_tunnel(uint8 lchip, sys_nh_db_mpls_tunnel_t* p_db_mpls,
            sys_wb_nh_mpls_tunnel_t *p_wb_mpls, uint8 sync, uint8 lsp_idx, uint8 spme_idx)
{
    uint8 index = 0;

    if (sync)
    {
        p_wb_mpls->tunnel_id = p_db_mpls->tunnel_id;
        p_wb_mpls->gport = p_db_mpls->gport;
        p_wb_mpls->l3ifid = lsp_idx?p_db_mpls->p_l3ifid:p_db_mpls->l3ifid;
        p_wb_mpls->flag = p_db_mpls->flag;
        p_wb_mpls->label_num = p_db_mpls->label_num;
        p_wb_mpls->sr_loop_num = p_db_mpls->sr_loop_num;
        p_wb_mpls->lsp_offset = p_db_mpls->lsp_offset;
        p_wb_mpls->lsp_ttl = p_db_mpls->lsp_ttl;
        sal_memset(p_wb_mpls->sr, 0, sizeof(sys_nh_mpls_sr_t)*SYS_MPLS_NH_MAX_TUNNEL_LABEL_NUM);
        if (p_db_mpls->pd->sr)
        {
            sal_memcpy(p_wb_mpls->sr, p_db_mpls->pd->sr, sizeof(sys_nh_mpls_sr_t)*p_db_mpls->sr_loop_num);
        }

        p_wb_mpls->l2edit_offset = p_db_mpls->l2edit_offset;
        p_wb_mpls->spme_offset = p_db_mpls->spme_offset;
        p_wb_mpls->spme_ttl = (p_db_mpls->spme_ttl_high << 4) + p_db_mpls->spme_ttl_low;
        p_wb_mpls->arp_id = p_db_mpls->arp_id;
        p_wb_mpls->loop_nhid = p_db_mpls->loop_nhid;
    }
    else
    {
        p_db_mpls->tunnel_id = p_wb_mpls->tunnel_id;
        p_db_mpls->gport = p_wb_mpls->gport;
        p_db_mpls->flag  = p_wb_mpls->flag;
        p_db_mpls->label_num  = p_wb_mpls->label_num;

        if (lsp_idx)
        {
            p_db_mpls->p_l3ifid = p_wb_mpls->l3ifid;
        }
        else
        {
            p_db_mpls->l3ifid =  p_wb_mpls->l3ifid;
        }
        p_db_mpls->lsp_offset = p_wb_mpls->lsp_offset;
        p_db_mpls->lsp_ttl = p_wb_mpls->lsp_ttl;
        if (p_db_mpls->lsp_offset)
        {
            if (CTC_FLAG_ISSET(p_db_mpls->flag, SYS_NH_MPLS_TUNNEL_FLAG_IS_SPME))
            {
                sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_SPME, 1, p_db_mpls->lsp_offset);
            }
            else
            {
                if (CTC_FLAG_ISSET(p_db_mpls->flag, SYS_NH_MPLS_TUNNEL_FLAG_IS_SR) && !DRV_IS_DUET2(lchip))
                {
                    sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS_12W, 1, p_db_mpls->lsp_offset);
                }
                else
                {
                    sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS, 1, p_db_mpls->lsp_offset);
                }
            }
        }

        p_db_mpls->l2edit_offset = p_wb_mpls->l2edit_offset;
        p_db_mpls->spme_offset = p_wb_mpls->spme_offset;
        p_db_mpls->spme_ttl_low = p_wb_mpls->spme_ttl & 0xF;
        p_db_mpls->spme_ttl_high = (p_wb_mpls->spme_ttl >> 4) & 0xF;
        p_db_mpls->arp_id= p_wb_mpls->arp_id;
        p_db_mpls->loop_nhid = p_wb_mpls->loop_nhid;

        if (CTC_FLAG_ISSET(p_db_mpls->flag, SYS_NH_MPLS_TUNNEL_FLAG_APS))
        {
            return CTC_E_NONE;
        }

        if (p_db_mpls->spme_offset)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_SPME, 1, p_db_mpls->spme_offset);
        }

        if (p_db_mpls->loop_nhid && p_wb_mpls->l2edit_offset)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, p_wb_mpls->l2edit_offset);
        }

        p_db_mpls->sr_loop_num = p_wb_mpls->sr_loop_num;
        if (p_db_mpls->sr_loop_num)
        {
            sys_nh_mpls_sr_t* p_sr = NULL;
            p_db_mpls->pd->sr = (sys_nh_mpls_sr_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_mpls_sr_t) *p_db_mpls->sr_loop_num);
            if (!p_db_mpls->pd->sr)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
                mem_free(p_db_mpls->pd);
                return CTC_E_NO_MEMORY;
            }
            sal_memset(p_db_mpls->pd->sr, 0, sizeof(sys_nh_mpls_sr_t) *p_db_mpls->sr_loop_num);
            sal_memcpy(p_db_mpls->pd->sr, p_wb_mpls->sr, sizeof(sys_nh_mpls_sr_t)*p_db_mpls->sr_loop_num);

            /*recover sr tunnel l3edit info*/
            for (index = 0; index < p_db_mpls->sr_loop_num; index++)
            {
                p_sr = p_db_mpls->pd->sr + index;
                if (p_sr->dsnh_offset)
                {
                    sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 1, p_sr->dsnh_offset);
                }
                if (p_sr->pw_offset && DRV_IS_DUET2(lchip))
                {
                    sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS, 1, p_sr->pw_offset);
                }
                if (p_sr->lsp_offset)
                {
                    sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS, 1, p_sr->lsp_offset);
                }
                if (p_sr->spme_offset)
                {
                    sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_SPME, 1, p_sr->spme_offset);
                }
                if (p_sr->l2edit_offset)
                {
                    sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, p_sr->l2edit_offset);
                }
            }

            if (!DRV_IS_DUET2(lchip) && p_sr->pw_offset)
            {
                sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS_12W, 1, p_sr->pw_offset);
            }
        }

        if (p_db_mpls->arp_id)
        {
            sys_nh_db_arp_t* p_arp = NULL;
            p_arp = (sys_usw_nh_lkup_arp_id(lchip, p_db_mpls->arp_id));
            if (NULL == p_arp)
            {
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Entry not exist \n");
                return CTC_E_NOT_EXIST;
            }
            p_arp->ref_cnt++;
        }

        /*restore edit information*/
        if (!p_db_mpls->arp_id && !p_db_mpls->loop_nhid && p_wb_mpls->l2edit_offset)
        {
            uint8 entry_type = 0;

            entry_type = CTC_FLAG_ISSET(p_db_mpls->flag , SYS_NH_MPLS_TUNNEL_FLAG_IS_L2EDIT8W)? SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_8W : SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W;
            if (p_wb_mpls->label_num == 0)
            {
                CTC_ERROR_RETURN(sys_usw_nh_offset_alloc_from_position(lchip, entry_type, 1, p_wb_mpls->l2edit_offset));
            }
            else
            {
                CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_wb_mpls->l2edit_offset));
            }
        }
    }
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_mapping_trill_nhinfo(uint8 lchip, sys_nh_info_com_t* p_nh_info_com, sys_wb_nh_info_com_t *p_wb_nh_info, uint8 sync)
{
    sys_nh_info_trill_t  *p_nh_info = (sys_nh_info_trill_t*)p_nh_info_com;

    if (sync)
    {
        p_wb_nh_info->info.trill.ingress_nickname = p_nh_info->ingress_nickname;
        p_wb_nh_info->info.trill.egress_nickname = p_nh_info->egress_nickname;
        p_wb_nh_info->info.trill.l3ifid = p_nh_info->l3ifid;
        p_wb_nh_info->info.trill.gport = p_nh_info->gport;
        p_wb_nh_info->info.trill.dsl3edit_offset = p_nh_info->dsl3edit_offset;
        p_wb_nh_info->info.trill.l2_edit_ptr = p_nh_info->l2_edit_ptr;
        p_wb_nh_info->info.trill.dest_vlan_ptr = p_nh_info->dest_vlan_ptr;
    }
    else
    {
        p_nh_info->ingress_nickname = p_wb_nh_info->info.trill.ingress_nickname;
        p_nh_info->egress_nickname = p_wb_nh_info->info.trill.egress_nickname;
        p_nh_info->l3ifid = p_wb_nh_info->info.trill.l3ifid;
        p_nh_info->gport = p_wb_nh_info->info.trill.gport;
        p_nh_info->dsl3edit_offset = p_wb_nh_info->info.trill.dsl3edit_offset;
        p_nh_info->l2_edit_ptr = p_wb_nh_info->info.trill.l2_edit_ptr;
        p_nh_info->dest_vlan_ptr = p_wb_nh_info->info.trill.dest_vlan_ptr;
        if (CTC_FLAG_ISSET(p_nh_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_L3EDIT))
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_TRILL + SYS_NH_TYPE_STEP_TO_INNER, 1, p_wb_nh_info->info.trill.dsl3edit_offset);
        }

        /*restore edit information*/
        if (p_nh_info->l2_edit_ptr)
        {
            uint8 entry_type = SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W;

            CTC_ERROR_RETURN(_sys_usw_nh_wb_restore_edit(lchip, entry_type, p_nh_info->l2_edit_ptr));
        }
    }

    return CTC_E_NONE;

}

STATIC int32
_sys_usw_nh_wb_mapping_fp(uint8 lchip, sys_nh_fp_db_t* p_db, sys_wb_nh_fp_t *p_wb, uint8 sync)
{
    if (sync)
    {
        p_wb->fp_id = p_db->fp_id;
        p_wb->l3_edit_ptr = p_db->l3_edit_ptr;
        p_wb->pair_edit_ptr = p_db->pair_edit_ptr;
        p_wb->alloc_en = p_db->alloc_en;
        p_wb->fp2 = p_db->fp2;
        p_wb->ext_mode = p_db->ext_mode;
        p_wb->is_internal = p_db->is_internal;
        p_wb->alu_prof_id = 0;
        p_wb->data_prof_id = 0;
        p_wb->l3chksum_prof_id = 0;
        p_wb->l4chksum_prof_id = 0;
        p_wb->rsv[0] = 0;
        p_wb->rsv[1] = 0;
        p_wb->rsv[2] = 0;
        if (p_db->p_alu_prof)
        {
            p_wb->alu_prof_id = p_db->p_alu_prof->profile_id;
        }
        if (p_db->p_data_prof)
        {
            p_wb->data_prof_id = p_db->p_data_prof->profile_id;
        }
        if (p_db->p_l3chksum_prof)
        {
            p_wb->l3chksum_prof_id = p_db->p_l3chksum_prof->profile_id;
        }
        if (p_db->p_l4chksum_prof)
        {
            p_wb->l4chksum_prof_id = p_db->p_l4chksum_prof->profile_id;
        }
    }
    else
    {
        uint32 cmd = 0;
        uint8 i = 0;
        sys_nh_fp_prof_t* p_prof = NULL;
        sys_nh_fp_prof_t prof;
        uint16 prof_id[4] = {p_wb->alu_prof_id, p_wb->data_prof_id, p_wb->l3chksum_prof_id,  p_wb->l4chksum_prof_id};
        uint32 tbl_id[4] = {DsL3EditFlexAluProfile_t, DsFlexEditInsertHeaderTemplate_t, DsPktRwL3ChkSumMaskProfile_t, DsPktRwL4ChkSumMaskProfile_t};
        uint8 type[4] = {SYS_NH_ENTRY_TYPE_FP_ALU_PROFILE, SYS_NH_ENTRY_TYPE_FP_DATA_PROFILE, SYS_NH_ENTRY_TYPE_FP_L3CHKSUM_PROFILE, SYS_NH_ENTRY_TYPE_FP_L4CHKSUM_PROFILE};
        uint32 tbl_id_fp2[4] = {DsXEditFlexAluProfile_t, DsXEditInsertHeaderTemplate_t, DsPktRwL3ChkSumMaskProfile_t, DsPktRwL4ChkSumMaskProfile_t};
        uint8 type_fp2[4] = {SYS_NH_ENTRY_TYPE_XFP_ALU_PROFILE, SYS_NH_ENTRY_TYPE_XFP_DATA_PROFILE, SYS_NH_ENTRY_TYPE_FP_L3CHKSUM_PROFILE, SYS_NH_ENTRY_TYPE_FP_L4CHKSUM_PROFILE};
        uint32 entry_type = 0;
        uint32 entry_type_pair = 0;

        p_db->fp_id            =  p_wb->fp_id ;
        p_db->l3_edit_ptr      =  p_wb->l3_edit_ptr;
        p_db->pair_edit_ptr    =  p_wb->pair_edit_ptr ;
        p_db->alloc_en         =  p_wb->alloc_en;
        p_db->fp2              =  p_wb->fp2;
        p_db->ext_mode         =  p_wb->ext_mode;
        p_db->is_internal      =  p_wb->is_internal;
        if (p_db->alloc_en)
        {
            sys_usw_opf_t opf;
            sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
            opf.pool_type = g_usw_nh_master[lchip]->fp_opf_type;
            opf.reverse = p_db->is_internal;
            sys_usw_opf_alloc_offset_from_position( SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, 1, p_db->fp_id);
        }

        entry_type = p_db->fp2? SYS_NH_ENTRY_TYPE_XFP_EDIT : SYS_NH_ENTRY_TYPE_L3EDIT_FP + SYS_NH_TYPE_STEP_TO_INNER;
        entry_type_pair = SYS_NH_ENTRY_TYPE_L3EDIT_FP;
        if (DRV_FROM_AT(lchip) && (SYS_NH_FP_INST_PAIR_EXT == p_db->ext_mode))
        {
            entry_type_pair = SYS_NH_ENTRY_TYPE_L3EDIT_FP + SYS_NH_TYPE_STEP_TO_INNER;
            entry_type = SYS_NH_ENTRY_TYPE_L3EDIT_FP;
        }

        if (p_db->l3_edit_ptr)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, entry_type, 1, p_db->l3_edit_ptr);
        }
        if (p_db->pair_edit_ptr)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, entry_type_pair, 1, p_db->pair_edit_ptr);
        }
        for (i = 0; i < 4; i++)
        {
            if (prof_id[i])
            {
                sal_memset(&prof, 0, sizeof(prof));
                cmd = DRV_IOR(p_db->fp2? tbl_id_fp2[i] : tbl_id[i], DRV_ENTRY_FLAG);
                DRV_IOCTL(lchip, prof_id[i], cmd, &prof.data);
                prof.profile_id = prof_id[i];
                prof.type = p_db->fp2? type_fp2[i] : type[i];
                CTC_ERROR_RETURN(ctc_spool_add(g_usw_nh_master[lchip]->p_fp_spool, &prof, NULL, &p_prof));

                if (0 == i)
                {
                    p_db->p_alu_prof = p_prof;
                }
                else if (1 == i)
                {
                    p_db->p_data_prof = p_prof;
                }
                else if (2 == i)
                {
                    p_db->p_l3chksum_prof = p_prof;
                }
                else if (3 == i)
                {
                    p_db->p_l4chksum_prof = p_prof;
                }
            }
            p_prof = NULL;
        }
    }
    return CTC_E_NONE;
}


int32
_sys_usw_nh_wb_restore_nhinfo(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_wb_nh_info_com_t wb_com;
    sys_wb_nh_info_com_t *p_wb_nh_info = &wb_com;
    sys_nh_info_com_t* p_nhinfo = NULL;
    uint32 db_entry_size = 0;
    uint32 entry_cnt = 0;
    int32 ret = 0;
    sys_usw_opf_t opf;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_NHID_INTERNAL;
    opf.multiple  = 1;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_info_com_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_com, 0, sizeof(sys_wb_nh_info_com_t));

    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8*)p_wb_nh_info, (uint8*)(p_wb_query->buffer) + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               p_wb_query->key_len + p_wb_query->data_len);
    entry_cnt++;
    db_entry_size = g_usw_nh_master[lchip]->db_size[p_wb_nh_info->nh_type];
    p_nhinfo = mem_malloc(MEM_NEXTHOP_MODULE, db_entry_size);
    if (NULL == p_nhinfo)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    sal_memset(p_nhinfo, 0, db_entry_size);

    p_nhinfo->hdr.dsnh_entry_num = p_wb_nh_info->hdr.dsnh_entry_num;
    p_nhinfo->hdr.nh_entry_type = p_wb_nh_info->nh_type;
    p_nhinfo->hdr.nh_entry_flags = p_wb_nh_info->hdr.nh_entry_flags;
    p_nhinfo->hdr.dsfwd_offset = p_wb_nh_info->hdr.dsfwd_offset;
    p_nhinfo->hdr.dsfwd1_offset = p_wb_nh_info->hdr.dsfwd1_offset;
    p_nhinfo->hdr.dsnh_offset = p_wb_nh_info->hdr.dsnh_offset;
    p_nhinfo->hdr.nh_id = p_wb_nh_info->nh_id;

    if ((p_nhinfo->hdr.dsnh_offset < g_usw_nh_master[lchip]->max_glb_nh_offset) && p_nhinfo->hdr.dsnh_entry_num)
    {
        if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
        {
            sys_usw_nh_set_glb_nh_offset(lchip, p_nhinfo->hdr.dsnh_offset, p_wb_nh_info->hdr.dsnh_entry_num*2 , TRUE);
        }
        else
        {
            sys_usw_nh_set_glb_nh_offset(lchip, p_nhinfo->hdr.dsnh_offset, p_wb_nh_info->hdr.dsnh_entry_num , TRUE);

        }
    }
    else if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_INT_ALLOC_DSNH) && p_nhinfo->hdr.dsnh_entry_num)
    {
        if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, p_nhinfo->hdr.dsnh_entry_num, p_nhinfo->hdr.dsnh_offset);
        }
        else
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, p_nhinfo->hdr.dsnh_entry_num, p_nhinfo->hdr.dsnh_offset);
        }
    }

    if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
    {
        sys_usw_nh_offset_alloc_from_position(lchip, (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)? SYS_NH_ENTRY_TYPE_FWD : SYS_NH_ENTRY_TYPE_FWD_HALF),
                                              1,
                                              p_nhinfo->hdr.dsfwd_offset);
    }
    if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1))
    {
        sys_usw_nh_offset_alloc_from_position(lchip, (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)?SYS_NH_ENTRY_TYPE_FWD1:SYS_NH_ENTRY_TYPE_FWD_HALF1),
                             1,
                             p_nhinfo->hdr.dsfwd1_offset);
    }
    switch(p_wb_nh_info->nh_type)
    {
        case SYS_NH_TYPE_IPUC:
            _sys_usw_nh_wb_mapping_ipuc_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_TOCPU:
        case SYS_NH_TYPE_DROP:
        case SYS_NH_TYPE_UNROV:
        case SYS_NH_TYPE_ILOOP:
            _sys_usw_nh_wb_mapping_special_nhinfo(p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_MISC:
            _sys_usw_nh_wb_mapping_misc_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_BRGUC:
            _sys_usw_nh_wb_mapping_brguc_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_RSPAN:
            _sys_usw_nh_wb_mapping_rspan_nhinfo(p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_IP_TUNNEL:
            _sys_usw_nh_wb_mapping_ip_tunnel_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_WLAN_TUNNEL:
            _sys_usw_nh_wb_mapping_wlan_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_SRV6:
            _sys_usw_nh_wb_mapping_srv6_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_OVERLAY_VNI:
            _sys_usw_nh_wb_mapping_ol_vni_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_OVERLAY:
            _sys_usw_nh_wb_mapping_overlay_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_MPLS:
            _sys_usw_nh_wb_mapping_mpls_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        case SYS_NH_TYPE_TRILL:
            _sys_usw_nh_wb_mapping_trill_nhinfo(lchip, p_nhinfo, p_wb_nh_info, 0);
            break;
        default:
            break;
    }

    ctc_hash_insert(g_usw_nh_master[lchip]->nhid_hash, p_nhinfo);
    if (p_wb_nh_info->nh_id >=  g_usw_nh_master[lchip]->max_external_nhid)
    {
        sys_usw_opf_alloc_offset_from_position(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, 1, p_wb_nh_info->nh_id);
        g_usw_nh_master[lchip]->internal_nh_used_num++;
    }
    g_usw_nh_master[lchip]->nhid_used_cnt[p_wb_nh_info->nh_type]++;
    CTC_WB_QUERY_ENTRY_END(p_wb_query);

    done:
    return ret;
}
extern int32
sys_usw_nh_wb_restore_ecmp_nhinfo(uint8 lchip,  sys_nh_info_com_t* p_nh_info_com,sys_wb_nh_info_ecmp_t *p_wb_nh_info);

int32
_sys_usw_nh_wb_restore_ecmp_mem(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_wb_nh_info_ecmp_mem_t     wb_mem_info;
    sys_wb_nh_info_ecmp_mem_t     *p_wb_mem_info = &wb_mem_info;
    sys_nh_info_com_t* p_nhinfo = NULL;
    void* p_mem_info = NULL;
    uint32 entry_cnt = 0;
    int32 ret = 0;
    uint32 nhid = 0;
    sys_nh_info_ecmp_t  *p_ecmp_info = NULL;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_info_ecmp_mem_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP_MEM);

    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_mem_info, 0, sizeof(sys_wb_nh_info_ecmp_mem_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_mem_info, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
        (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;

    nhid = p_wb_mem_info->nhid;

    CTC_ERROR_DUMP(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo));
    if (!p_nhinfo)
    {
        ret = CTC_E_INVALID_CONFIG;
        goto done;
    }

    p_ecmp_info = (sys_nh_info_ecmp_t*)p_nhinfo;

    if (p_wb_mem_info->mem_index < p_ecmp_info->ecmp_cnt)
    {
        p_ecmp_info->nh_array[p_wb_mem_info->mem_index] = p_wb_mem_info->mem_nh;
        if (0 == p_ecmp_info->mem_is_tunnel)
        {
            /*Get member nhid */
            CTC_ERROR_DUMP(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_wb_mem_info->mem_nh, (sys_nh_info_com_t**)&p_mem_info));
            if (!p_mem_info)
            {
                ret = CTC_E_INVALID_CONFIG;
                goto done;
            }
        }
        else
        {
            p_mem_info = (void*)_sys_usw_nh_lkup_srh_id(lchip, p_wb_mem_info->mem_nh);
            if (NULL == p_mem_info)
            {
                ret = CTC_E_INVALID_CONFIG;
                goto done;
            }
        }
        CTC_ERROR_DUMP(sys_usw_nh_ecmp_add_ref_list(lchip, p_ecmp_info, p_mem_info));
    }

    CTC_WB_QUERY_ENTRY_END(p_wb_query);

    done:
    return ret;
}

int32
_sys_usw_nh_wb_restore_ecmp(uint8 lchip,  ctc_wb_query_t *p_wb_query, uint8 is_hecmp)
{
    sys_wb_nh_info_ecmp_t     wb_nh_info;
    sys_wb_nh_info_ecmp_t     *p_wb_nh_info = &wb_nh_info;
    sys_nh_info_com_t* p_nhinfo = NULL;
    uint32 db_entry_size = 0;
    uint32 entry_cnt = 0;
    int32 ret = 0;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_info_ecmp_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_nh_info, 0, sizeof(sys_wb_nh_info_ecmp_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_nh_info, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
        (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;
    db_entry_size = g_usw_nh_master[lchip]->db_size[p_wb_nh_info->nh_type];
    p_nhinfo = mem_malloc(MEM_NEXTHOP_MODULE, db_entry_size);
    if (NULL == p_nhinfo)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    sal_memset(p_nhinfo, 0, db_entry_size);

    p_nhinfo->hdr.dsnh_entry_num = p_wb_nh_info->hdr.dsnh_entry_num;
    p_nhinfo->hdr.nh_entry_type = p_wb_nh_info->nh_type;
    p_nhinfo->hdr.nh_entry_flags = p_wb_nh_info->hdr.nh_entry_flags;

    p_nhinfo->hdr.dsfwd_offset = p_wb_nh_info->hdr.dsfwd_offset;
    p_nhinfo->hdr.dsfwd1_offset = p_wb_nh_info->hdr.dsfwd1_offset;
    p_nhinfo->hdr.dsnh_offset = p_wb_nh_info->hdr.dsnh_offset;
    p_nhinfo->hdr.nh_id = p_wb_nh_info->nh_id;

    sys_usw_nh_wb_restore_ecmp_nhinfo(lchip, p_nhinfo, p_wb_nh_info);

    ctc_hash_insert(g_usw_nh_master[lchip]->nhid_hash, p_nhinfo);
    g_usw_nh_master[lchip]->nhid_used_cnt[p_wb_nh_info->nh_type]++;

    is_hecmp = ((sys_nh_info_ecmp_t *)p_nhinfo)->h_ecmp_en;
    if ( is_hecmp && DRV_IS_TSINGMA(lchip))
    {
        g_usw_nh_master[lchip]->cur_ecmp_cnt += g_usw_nh_master[lchip]->hecmp_mem_num;
    }
    else
    {
        g_usw_nh_master[lchip]->cur_ecmp_cnt++;
    }
    CTC_WB_QUERY_ENTRY_END(p_wb_query);

    done:
    return ret;
}


int32
_sys_usw_nh_wb_restore_aps(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_wb_nh_info_aps_t     wb_nh_info;
    sys_wb_nh_info_aps_t     *p_wb_nh_info = &wb_nh_info;
    sys_nh_info_com_t* p_nhinfo = NULL;
    uint32 db_entry_size = 0;
    uint32 entry_cnt = 0;
    int32 ret = 0;
    sys_nh_info_com_t* p_nh_com_info = NULL;
    sys_nh_info_aps_t* p_nh_aps = NULL;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_info_aps_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_APS);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_nh_info, 0, sizeof(sys_wb_nh_info_aps_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_nh_info, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
        (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;
    db_entry_size = g_usw_nh_master[lchip]->db_size[p_wb_nh_info->nh_type];
    p_nhinfo = mem_malloc(MEM_NEXTHOP_MODULE, db_entry_size);
    if (NULL == p_nhinfo)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    sal_memset(p_nhinfo, 0, db_entry_size);
    p_nh_aps = (sys_nh_info_aps_t* )p_nhinfo;

    p_nhinfo->hdr.dsnh_entry_num = p_wb_nh_info->hdr.dsnh_entry_num;
    p_nhinfo->hdr.nh_entry_type = p_wb_nh_info->nh_type;
    p_nhinfo->hdr.nh_entry_flags = p_wb_nh_info->hdr.nh_entry_flags;

    p_nhinfo->hdr.dsfwd_offset = p_wb_nh_info->hdr.dsfwd_offset;
    p_nhinfo->hdr.dsfwd1_offset = p_wb_nh_info->hdr.dsfwd1_offset;
    p_nhinfo->hdr.dsnh_offset = p_wb_nh_info->hdr.dsnh_offset;
    p_nhinfo->hdr.nh_id = p_wb_nh_info->nh_id;

    p_nh_aps->aps_group_id = p_wb_nh_info->aps_group_id;
    p_nh_aps->w_nexthop_id = p_wb_nh_info->w_nexthop_id;
    p_nh_aps->p_nexthop_id = p_wb_nh_info->p_nexthop_id;
    p_nh_aps->assign_port = p_wb_nh_info->assign_port;
    p_nh_aps->arp_num = p_wb_nh_info->arp_num;
    p_nh_aps->aps_xcon_met = p_wb_nh_info->aps_xcon_met;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_nh_aps->w_nexthop_id, (sys_nh_info_com_t**)&p_nh_com_info));
    _sys_usw_nh_aps_update_ref_list(lchip, p_nh_aps, p_nh_com_info, 0);
    if (p_nh_aps->p_nexthop_id)
    {
        CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_nh_aps->p_nexthop_id, (sys_nh_info_com_t**)&p_nh_com_info));
        _sys_usw_nh_aps_update_ref_list(lchip, p_nh_aps, p_nh_com_info, 0);
    }

   if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
   {
       sys_usw_nh_offset_alloc_from_position(lchip, (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)?SYS_NH_ENTRY_TYPE_FWD:SYS_NH_ENTRY_TYPE_FWD_HALF),
                            1,
                            p_nhinfo->hdr.dsfwd_offset);
   }
   if (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1))
   {
       sys_usw_nh_offset_alloc_from_position(lchip, (CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W)?SYS_NH_ENTRY_TYPE_FWD1:SYS_NH_ENTRY_TYPE_FWD_HALF1),
                            1,
                            p_nhinfo->hdr.dsfwd1_offset);
   }

    ctc_hash_insert(g_usw_nh_master[lchip]->nhid_hash, p_nhinfo);
    g_usw_nh_master[lchip]->nhid_used_cnt[p_wb_nh_info->nh_type]++;

    CTC_WB_QUERY_ENTRY_END(p_wb_query);

    done:
    return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_restore_mcast_member(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_wb_nh_info_mcast_mem_t wb_mem_info;
    sys_wb_nh_info_mcast_mem_t wb_mem_logic;
    sys_wb_nh_info_mcast_mem_t *p_wb_mem_info = &wb_mem_info;
    sys_wb_nh_info_mcast_mem_t *p_wb_mem_logic = &wb_mem_logic;
    sys_nh_info_mcast_t *p_mcast_info = NULL;
    sys_nh_mcast_meminfo_t	*p_member_info = NULL;
    uint16 loop = 0;
    uint32 entry_cnt = 0;
    uint8 entry_num = 0;
    int32 ret = 0;
    sys_nh_info_com_t* p_nh_com_info = NULL;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_info_mcast_mem_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_MEM);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_mem_info, 0, sizeof(sys_wb_nh_info_mcast_mem_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_mem_info, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;

    CTC_ERROR_GOTO(sys_usw_nh_get_nhinfo_by_nhid(lchip, p_wb_mem_info->mcast_nhid, (sys_nh_info_com_t**)&p_nh_com_info), ret, done);
    p_mcast_info = (sys_nh_info_mcast_t*)p_nh_com_info;

    if (p_wb_mem_info->member_type == SYS_NH_PARAM_MCAST_MEM_LOCAL_WITH_NH)
    {
        sys_nh_info_mcast_t    *p_mcast_mem_info = NULL;
        ret = sys_usw_nh_get_nhinfo_by_nhid(lchip, p_wb_mem_info->ref_nhid, (sys_nh_info_com_t**)&p_nh_com_info);
        if ((CTC_E_NONE == ret) && CTC_FLAG_ISSET(p_nh_com_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_MCAST_PROFILE))
        {
            p_mcast_mem_info = (sys_nh_info_mcast_t*)p_nh_com_info;
            p_mcast_mem_info->profile_ref_cnt++;
            p_mcast_info->profile_nh_id = p_wb_mem_info->ref_nhid;
            p_mcast_info->profile_met_offset = p_wb_mem_info->dsmet_offset;
            continue;
        }
        if(ret)
        {
            CTC_ERROR_DUMP(ret);
            ret = CTC_E_NONE;
        }

    }

    p_member_info = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_mcast_meminfo_t));
    if (NULL == p_member_info)
    {
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_member_info, 0, sizeof(sys_nh_mcast_meminfo_t));
    p_member_info->dsmet.flag = p_wb_mem_info->flag;
    p_member_info->dsmet.logic_port = p_wb_mem_info->logic_port;
    p_member_info->dsmet.dsmet_offset = p_wb_mem_info->dsmet_offset;
    p_member_info->dsmet.next_dsmet_offset = p_wb_mem_info->next_dsmet_offset;
    p_member_info->dsmet.dsnh_offset = p_wb_mem_info->dsnh_offset;
    p_member_info->dsmet.ref_nhid = p_wb_mem_info->ref_nhid;
    p_member_info->dsmet.ucastid = p_wb_mem_info->ucastid;
    p_member_info->dsmet.replicate_num = p_wb_mem_info->replicate_num;
    p_member_info->dsmet.free_dsnh_offset_cnt = p_wb_mem_info->free_dsnh_offset_cnt;
    p_member_info->dsmet.member_type = p_wb_mem_info->member_type  ;
    p_member_info->dsmet.port_type = p_wb_mem_info->port_type  ;
    p_member_info->dsmet.entry_type = p_wb_mem_info->entry_type  ;
    p_member_info->dsmet.fid = p_wb_mem_info->fid;

    if ((p_wb_mem_info->member_type == SYS_NH_PARAM_IPMC_MEM_LOCAL_LOGIC_REP)&&(!DRV_FROM_TMM(lchip)))
    {
        if ((p_member_info->dsmet.vid_list == NULL) && p_wb_mem_info->replicate_num)
        {
            p_member_info->dsmet.vid_list = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(uint16) * SYS_NH_LOGICAL_REPLI_MAX_NUM);
            if (NULL == p_member_info->dsmet.vid_list)
            {
                return CTC_E_NO_MEMORY;
            }
        }
        else if(0 == p_wb_mem_info->replicate_num)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 1, p_wb_mem_info->dsnh_offset);
        }
    }

    if (CTC_FLAG_ISSET(p_member_info->dsmet.flag, SYS_NH_DSMET_FLAG_LOGIC_REPLI_EN) && DRV_FROM_TMM(lchip))
    {
        sys_nh_mcast_meminfo_t* p_rep_node = NULL;
        ctc_list_pointer_init(&(p_member_info->dsmet.logic_rep_list));
        for (loop = 0; loop < p_wb_mem_info->replicate_num; loop++)
        {
            p_rep_node = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_mcast_meminfo_t));
            if (!p_rep_node)
            {
                return CTC_E_NO_MEMORY;
            }
            sal_memset(p_rep_node, 0, sizeof(sys_nh_mcast_meminfo_t));
            sal_memcpy((uint8 *)p_wb_mem_logic, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               (p_wb_query->key_len + p_wb_query->data_len));
            p_rep_node->dsmet.flag = p_wb_mem_logic->flag;
            p_rep_node->dsmet.logic_port = p_wb_mem_logic->logic_port;
            p_rep_node->dsmet.dsmet_offset = p_wb_mem_logic->dsmet_offset;
            p_rep_node->dsmet.next_dsmet_offset = p_wb_mem_logic->next_dsmet_offset;
            p_rep_node->dsmet.dsnh_offset = p_wb_mem_logic->dsnh_offset;
            p_rep_node->dsmet.ref_nhid = p_wb_mem_logic->ref_nhid;
            p_rep_node->dsmet.ucastid = p_wb_mem_logic->ucastid;
            p_rep_node->dsmet.replicate_num = p_wb_mem_logic->replicate_num;
            p_rep_node->dsmet.free_dsnh_offset_cnt = p_wb_mem_logic->free_dsnh_offset_cnt;
            p_rep_node->dsmet.member_type = p_wb_mem_logic->member_type  ;
            p_rep_node->dsmet.port_type = p_wb_mem_logic->port_type  ;
            p_rep_node->dsmet.entry_type = p_wb_mem_logic->entry_type  ;
            p_rep_node->dsmet.fid = p_wb_mem_logic->fid;
            ctc_list_pointer_insert_tail(&p_member_info->dsmet.logic_rep_list, &(p_rep_node->list_head));
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_LOGIC_REP, 1, p_wb_mem_logic->dsmet_offset);
            entry_cnt++;
        }
    }
    else if (p_wb_mem_info->member_type == SYS_NH_PARAM_IPMC_MEM_LOCAL_LOGIC_REP && (!DRV_FROM_TMM(lchip)) && p_member_info->dsmet.vid_list)
    {
        p_member_info->dsmet.vid = p_wb_mem_info->vid;

        for (loop = 0; loop < p_wb_mem_info->replicate_num; loop++)
        {
            sal_memcpy((uint8 *)p_wb_mem_logic, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
           (p_wb_query->key_len + p_wb_query->data_len));
            p_member_info->dsmet.vid_list[loop+1] = p_wb_mem_logic->vid;
            entry_cnt++;
        }

        if (p_member_info->dsmet.vid_list)
        {
             p_member_info->dsmet.vid_list[0] = p_member_info->dsmet.vid;
        }
        entry_num = p_wb_mem_info->replicate_num + p_wb_mem_info->free_dsnh_offset_cnt + 1;
        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, entry_num, p_wb_mem_info->dsnh_offset);
    }
    else
    {
        p_member_info->dsmet.vid = p_wb_mem_info->vid;
        p_member_info->dsmet.cvid = p_wb_mem_info->cvid;
    }

    if ((p_wb_mem_info->dsmet_offset != p_wb_mem_info->basic_met_offset) && (SYS_NH_PARAM_MEM_LOGIC_REP_LIST != p_wb_mem_info->member_type))
    {
        if (CTC_FLAG_ISSET(p_wb_mem_info->flag, SYS_NH_DSMET_FLAG_IS_MCAST_APS) &&
            !CTC_FLAG_ISSET(p_wb_mem_info->flag, SYS_NH_DSMET_FLAG_IS_BASIC_MET))
        {
            sys_usw_nh_offset_alloc_from_position(lchip, p_wb_mem_info->entry_type, 2, p_wb_mem_info->dsmet_offset);
        }
        else
        {
            sys_usw_nh_offset_alloc_from_position(lchip, p_wb_mem_info->entry_type, 1, p_wb_mem_info->dsmet_offset);
        }
    }

    if (DRV_FROM_AT(lchip) && CTC_FLAG_ISSET(p_wb_mem_info->flag, SYS_NH_DSMET_FLAG_USE_PBM))
    {
        uint8 i = 0;
        sys_met_t dsmet;
        sal_memset(&dsmet, 0, sizeof(dsmet));
        CTC_ERROR_RETURN(sys_usw_nh_read_asic_table(lchip, p_wb_mem_info->entry_type, p_wb_mem_info->dsmet_offset, &dsmet));
        for (i = 0; i < CTC_PORT_BITMAP_IN_WORD; i++)
        {
            if (dsmet.port_bitmap[i])
            {
                p_member_info->dsmet.min_port_range = i;
                break;
            }
        }
        for (i = CTC_PORT_BITMAP_IN_WORD; i > 0; i--)
        {
            if (dsmet.port_bitmap[i - 1])
            {
                p_member_info->dsmet.max_port_range = i - 1;
                break;
            }
        }
    }

    /*add one member to mcast group*/
    ctc_list_pointer_insert_tail(&p_mcast_info->p_mem_list, &(p_member_info->list_head));

    CTC_WB_QUERY_ENTRY_END(p_wb_query);

    done:
    return ret;
}

int32
_sys_usw_nh_wb_restore_mcast(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_wb_nh_info_mcast_t wb_mcast_info;
    sys_wb_nh_info_mcast_t *p_wb_mcast_info = &wb_mcast_info;
    sys_nh_info_mcast_t    *p_mcast_info = NULL;
    sys_usw_opf_t opf;
    uint32 entry_cnt = 0;
    int32 ret = 0;

    sal_memset(&opf, 0, sizeof(sys_usw_opf_t));
    opf.pool_type = g_usw_nh_master[lchip]->nh_opf_type;
    opf.pool_index = OPF_NH_NHID_INTERNAL;
    opf.multiple  = 1;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_info_mcast_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_MCAST);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_mcast_info, 0, sizeof(sys_wb_nh_info_mcast_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_mcast_info, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;
    p_mcast_info = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_info_mcast_t));
    if (NULL == p_mcast_info)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_mcast_info, 0, sizeof(sys_nh_info_mcast_t));
    ctc_list_pointer_init(&p_mcast_info->p_mem_list);
    if (CTC_FLAG_ISSET(p_wb_mcast_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD))
    {
        sys_usw_nh_offset_alloc_from_position(lchip,
            CTC_FLAG_ISSET(p_wb_mcast_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W) ? SYS_NH_ENTRY_TYPE_FWD:SYS_NH_ENTRY_TYPE_FWD_HALF,
                                                     1, p_wb_mcast_info->hdr.dsfwd_offset);
    }

    if (CTC_FLAG_ISSET(p_wb_mcast_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_HAVE_DSFWD1))
    {

        sys_usw_nh_offset_alloc_from_position(lchip,
            CTC_FLAG_ISSET(p_wb_mcast_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_DSFWD_IS_6W) ? SYS_NH_ENTRY_TYPE_FWD1:SYS_NH_ENTRY_TYPE_FWD_HALF1,
                                                     1, p_wb_mcast_info->hdr.dsfwd1_offset);
    }

    if (CTC_FLAG_ISSET(p_wb_mcast_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_MCAST_PROFILE))
    {
        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_MET, 1, p_wb_mcast_info->basic_met_offset);
    }

    p_mcast_info->basic_met_offset = p_wb_mcast_info->basic_met_offset;
    p_mcast_info->physical_replication_num = p_wb_mcast_info->physical_replication_num;
    p_mcast_info->mcast_flag = p_wb_mcast_info->mcast_flag ;
    p_mcast_info->profile_met_offset = wb_mcast_info.profile_met_offset;
    p_mcast_info->profile_nh_id = wb_mcast_info.profile_nh_id;
    p_mcast_info->hdr.dsnh_entry_num = p_wb_mcast_info->hdr.dsnh_entry_num;
    p_mcast_info->hdr.nh_entry_flags = p_wb_mcast_info->hdr.nh_entry_flags;
    p_mcast_info->hdr.nh_entry_type = SYS_NH_TYPE_MCAST;

    p_mcast_info->hdr.dsfwd_offset = p_wb_mcast_info->hdr.dsfwd_offset;
    p_mcast_info->hdr.dsfwd1_offset = p_wb_mcast_info->hdr.dsfwd1_offset;

    p_mcast_info->hdr.dsnh_offset = p_wb_mcast_info->hdr.dsnh_offset;
    p_mcast_info->hdr.nh_id = p_wb_mcast_info->nh_id;
    p_mcast_info->stats_ptr = p_wb_mcast_info->hdr.dsnh_offset;
    p_mcast_info->pp_bmp = p_wb_mcast_info->pp_bmp;

    /*add one mcast group*/
    if (NULL == ctc_hash_insert(g_usw_nh_master[lchip]->nhid_hash, p_mcast_info))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }

    if (p_mcast_info->hdr.nh_id >= g_usw_nh_master[lchip]->max_external_nhid )
    {
        sys_usw_opf_alloc_offset_from_position(SYS_MAP_LCHIP(lchip, CTC_FEATURE_NEXTHOP), &opf, 1, p_mcast_info->hdr.nh_id);
        g_usw_nh_master[lchip]->internal_nh_used_num++;
    }

    if (!CTC_FLAG_ISSET(p_wb_mcast_info->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_MCAST_PROFILE))
    {
        CTC_ERROR_RETURN(_sys_usw_nh_set_glb_met_offset(lchip, p_mcast_info->basic_met_offset,
            ((g_usw_nh_master[lchip]->met_mode || CTC_FLAG_ISSET(p_mcast_info->mcast_flag, SYS_NH_INFO_MCAST_FLAG_2X_GRP_ID))? 2 : 1), TRUE));

        if (FALSE ==  ctc_vector_add(g_usw_nh_master[lchip]->mcast_group_vec, p_mcast_info->basic_met_offset, p_mcast_info))
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;

        }
    }
    g_usw_nh_master[lchip]->nhid_used_cnt[SYS_NH_TYPE_MCAST]++;

    CTC_WB_QUERY_ENTRY_END(p_wb_query);


    done:
    return ret;
}

int32
_sys_usw_nh_wb_restore_mpls_tunnel(uint8 lchip,  ctc_wb_query_t *p_wb_query, uint8 is_aps_separate)
{
    sys_wb_nh_mpls_tunnel_t  wb_mpls_tunnel;
    sys_wb_nh_mpls_tunnel_t  *p_wb_mpls_tunnel = &wb_mpls_tunnel;
    sys_nh_db_mpls_tunnel_t* p_mpls_tunnel = NULL;
    uint32 entry_cnt = 0;
    int32 ret = 0;
    uint8 lsp_cnt = 1;
    uint8 spme_cnt = 1;
    uint8 lsp_index = 0;
    uint8 spme_index = 0;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_mpls_tunnel_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MPLS_TUNNEL);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_mpls_tunnel, 0, sizeof(sys_wb_nh_mpls_tunnel_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_mpls_tunnel, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
        (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;

    if (is_aps_separate != CTC_FLAG_ISSET(p_wb_mpls_tunnel->flag, SYS_NH_MPLS_TUNNEL_FLAG_APS))
    {
        continue;
    }

    p_mpls_tunnel  = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_mpls_tunnel_t));
    if (NULL == p_mpls_tunnel)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_mpls_tunnel, 0, sizeof(sys_nh_db_mpls_tunnel_t));

    p_mpls_tunnel->pd  = (sys_nh_info_mpls_tnl_pdata_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_info_mpls_tnl_pdata_t));
    if (!p_mpls_tunnel->pd)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_mpls_tunnel->pd, 0, sizeof(sys_nh_info_mpls_tnl_pdata_t));

    lsp_cnt = 1;
    spme_cnt = 1;
    if (CTC_FLAG_ISSET(p_wb_mpls_tunnel->flag, SYS_NH_MPLS_TUNNEL_FLAG_APS))
    {
        lsp_cnt = 2;
    }

    for (lsp_index = 0; lsp_index < lsp_cnt; lsp_index++)
    {
        for (spme_index = 0; spme_index < spme_cnt; spme_index++)
        {
            if (lsp_index || spme_index)
            {
                sal_memcpy((uint8 *)p_wb_mpls_tunnel, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
                           (p_wb_query->key_len + p_wb_query->data_len));
                entry_cnt++;
            }
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_mpls_tunnel(lchip, p_mpls_tunnel, p_wb_mpls_tunnel, 0, lsp_index, spme_index));
        }
    }

    if (is_aps_separate)
    {
        sys_nh_db_mpls_tunnel_t* p_w_tunnel = NULL;
        sys_nh_db_mpls_tunnel_t* p_p_tunnel = NULL;
        sys_nh_tunnel_ref_list_node_t* p_tunnel_list_node = NULL;

        CTC_ERROR_RETURN(sys_usw_nh_lkup_mpls_tunnel(lchip, p_mpls_tunnel->l3ifid, &p_w_tunnel));
        CTC_ERROR_RETURN(sys_usw_nh_lkup_mpls_tunnel(lchip, p_mpls_tunnel->p_l3ifid, &p_p_tunnel));
        if (!p_w_tunnel || !p_p_tunnel)
        {
            return CTC_E_NOT_EXIST;
        }

        p_tunnel_list_node = (sys_nh_tunnel_ref_list_node_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_tunnel_ref_list_node_t));
        if (p_tunnel_list_node == NULL)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;
        }
        p_tunnel_list_node->p_ref_node = p_mpls_tunnel;
        p_tunnel_list_node->p_next = p_w_tunnel->pd->p_tunnel_list;
        p_w_tunnel->pd->p_tunnel_list = p_tunnel_list_node;

        p_tunnel_list_node = (sys_nh_tunnel_ref_list_node_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_tunnel_ref_list_node_t));
        if (p_tunnel_list_node == NULL)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;
        }
        p_tunnel_list_node->p_ref_node = p_mpls_tunnel;
        p_tunnel_list_node->p_next = p_p_tunnel->pd->p_tunnel_list;
        p_p_tunnel->pd->p_tunnel_list = p_tunnel_list_node;
    }

    if (!ctc_vector_add(g_usw_nh_master[lchip]->tunnel_id_vec, p_mpls_tunnel->tunnel_id, p_mpls_tunnel))
    {
        return CTC_E_NO_MEMORY;
    }
    CTC_WB_QUERY_ENTRY_END(p_wb_query);
 done:
    return ret;
}

int32
_sys_usw_nh_wb_restore_arp(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{

	sys_nh_db_arp_t* p_db_arp = NULL;
	sys_wb_nh_arp_t wb_arp;
	sys_wb_nh_arp_t *p_wb_arp = &wb_arp;

    uint32 entry_cnt = 0;
    int32 ret = 0;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_arp_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ARP);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb_arp, 0, sizeof(sys_wb_nh_arp_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_arp, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
        (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;
    p_db_arp  = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_arp_t));
    if (NULL == p_db_arp)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
			return CTC_E_NO_MEMORY;

    }

    sal_memset(p_db_arp, 0, sizeof(sys_nh_db_arp_t));

    _sys_usw_nh_wb_mapping_arp(lchip, p_db_arp,p_wb_arp,0);

    if(NULL == ctc_hash_insert(g_usw_nh_master[lchip]->arp_id_hash, p_db_arp))
    {
    	SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No Memory \n");
			return CTC_E_NO_MEMORY;

   	}
    CTC_WB_QUERY_ENTRY_END(p_wb_query);
 done:
    return ret;
}

int32
_sys_usw_nh_wb_restore_nh_master(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_wb_nh_master_t   *p_wb_master = NULL;
    uint32 entry_cnt = 0;
    int32 ret = CTC_E_NONE;
    uint32*       p_dsnh;
    DsNextHop8W_m dsnh8w;
    uint8 index = 0;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_master_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER);
    p_wb_master = (sys_wb_nh_master_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_wb_nh_master_t));
    if (NULL == p_wb_master)
    {
        return CTC_E_NO_MEMORY;
    }
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(p_wb_master, 0, sizeof(sys_wb_nh_master_t));

    CTC_ERROR_GOTO(ctc_wb_query_entry(p_wb_query), ret, out);

    if (p_wb_query->valid_cnt != 0)
    {
        sal_memcpy((uint8*)p_wb_master, (uint8*)(p_wb_query->buffer)+entry_cnt*(p_wb_query->key_len + p_wb_query->data_len),
            (p_wb_query->key_len+p_wb_query->data_len));

        if (CTC_WB_VERSION_CHECK(SYS_WB_VERSION_NEXTHOP, p_wb_master->version))
        {
            ret = CTC_E_VERSION_MISMATCH;
            goto out;
        }

        if (g_usw_nh_master[lchip]->pkt_nh_edit_mode != p_wb_master->pkt_nh_edit_mode)
        {
            ret = CTC_E_VERSION_MISMATCH;
            goto out;
        }

        if ((g_usw_nh_master[lchip]->max_external_nhid > p_wb_master->max_external_nhid) ||
            (g_usw_nh_master[lchip]->max_tunnel_id > p_wb_master->max_tunnel_id)
            ||(g_usw_nh_master[lchip]->max_srh_id > p_wb_master->max_srh_id) )
        {
            ret = CTC_E_VERSION_MISMATCH;
            goto out;
        }

        g_usw_nh_master[lchip]->max_external_nhid = p_wb_master->max_external_nhid;
        g_usw_nh_master[lchip]->max_tunnel_id  = p_wb_master->max_tunnel_id;
        g_usw_nh_master[lchip]->max_srh_id  = p_wb_master->max_srh_id;
        g_usw_nh_master[lchip]->max_ecmp  = p_wb_master->max_ecmp;
        g_usw_nh_master[lchip]->max_ecmp_group_num = p_wb_master->max_ecmp_group_num;
        g_usw_nh_master[lchip]->cur_ecmp_cnt  = p_wb_master->cur_ecmp_cnt;
        g_usw_nh_master[lchip]->ipmc_logic_replication = p_wb_master->ipmc_logic_replication;
        g_usw_nh_master[lchip]->ecmp_if_resolved_l2edit = p_wb_master->ecmp_if_resolved_l2edit;
        g_usw_nh_master[lchip]->reflective_resolved_dsfwd_offset = p_wb_master->reflective_resolved_dsfwd_offset;
        g_usw_nh_master[lchip]->pkt_nh_edit_mode = p_wb_master->pkt_nh_edit_mode;
        g_usw_nh_master[lchip]->reflective_brg_en = p_wb_master->reflective_brg_en;
        g_usw_nh_master[lchip]->udf_profile_bitmap = p_wb_master->udf_profile_bitmap;
        g_usw_nh_master[lchip]->efd_nh_id = p_wb_master->efd_nh_id;
        g_usw_nh_master[lchip]->outer_l2_ptr = p_wb_master->outer_l2_ptr;
        g_usw_nh_master[lchip]->outer_l2_ptr_ref = p_wb_master->outer_l2_ptr_ref;
        g_usw_nh_master[lchip]->rsv_l2edit_ptr = p_wb_master->rsv_l2edit_ptr;
        g_usw_nh_master[lchip]->rsv_nh_ptr = p_wb_master->rsv_nh_ptr;
        g_usw_nh_master[lchip]->vxlan_mode = p_wb_master->vxlan_mode;
        g_usw_nh_master[lchip]->hecmp_mem_num = p_wb_master->hecmp_mem_num;
        g_usw_nh_master[lchip]->rsv_iloop_nh = p_wb_master->rsv_iloop_nh;
        g_usw_nh_master[lchip]->bpe_mc_en = p_wb_master->bpe_mc_en;
        g_usw_nh_master[lchip]->rsv_l3edit_for_nsh = p_wb_master->rsv_l3edit_for_nsh;
        g_usw_nh_master[lchip]->srv6_resolved_l2edit = p_wb_master->srv6_resolved_l2edit;
        g_usw_nh_master[lchip]->rsv_l3edit_for_igs_edit = p_wb_master->rsv_l3edit_for_igs_edit;
        g_usw_nh_master[lchip]->rsv_xedit_for_igs_edit = p_wb_master->rsv_xedit_for_igs_edit;
        g_usw_nh_master[lchip]->gem_port_edit_num = p_wb_master->gem_port_edit_num;
        g_usw_nh_master[lchip]->gem_port_edit_base = p_wb_master->gem_port_edit_base;
        sal_memcpy(g_usw_nh_master[lchip]->pon_mc_dsnh, p_wb_master->pon_mc_dsnh, sizeof(uint32)*SYS_NH_PON_MC_DSNH_NUM);
        if (g_usw_nh_master[lchip]->rsv_l2edit_ptr)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W_RW, 1, g_usw_nh_master[lchip]->rsv_l2edit_ptr);
        }
        if (g_usw_nh_master[lchip]->rsv_nh_ptr)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 1, g_usw_nh_master[lchip]->rsv_nh_ptr);
        }
        if (g_usw_nh_master[lchip]->outer_l2_ptr)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, g_usw_nh_master[lchip]->outer_l2_ptr);
        }
        if (g_usw_nh_master[lchip]->rsv_l3edit_for_nsh)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_ADD_RAW, 1, g_usw_nh_master[lchip]->rsv_l3edit_for_nsh);
        }
        if (g_usw_nh_master[lchip]->srv6_resolved_l2edit)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 1, g_usw_nh_master[lchip]->srv6_resolved_l2edit);
        }
        if (g_usw_nh_master[lchip]->rsv_l3edit_for_igs_edit)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_TUNNEL_V4, 1, g_usw_nh_master[lchip]->rsv_l3edit_for_igs_edit);
        }
        if (g_usw_nh_master[lchip]->rsv_xedit_for_igs_edit)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_XFP_EDIT, 1, g_usw_nh_master[lchip]->rsv_xedit_for_igs_edit);
        }
        if (g_usw_nh_master[lchip]->gem_port_edit_num)
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_FLEX_8W, g_usw_nh_master[lchip]->gem_port_edit_num, g_usw_nh_master[lchip]->gem_port_edit_base);
        }
        for(index=0; index<SYS_NH_PON_MC_DSNH_NUM; index++)
        {
            if (0 != g_usw_nh_master[lchip]->pon_mc_dsnh[index])
            {
                sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, 1, g_usw_nh_master[lchip]->pon_mc_dsnh[index]);
            }
        }
        sal_memcpy(g_usw_nh_master[lchip]->udf_ether_type, p_wb_master->udf_ether_type, sizeof(g_usw_nh_master[lchip]->udf_ether_type));
        sal_memcpy(g_usw_nh_master[lchip]->cw_ref_cnt, p_wb_master->cw_ref_cnt, SYS_NH_CW_NUM*sizeof(uint16));

        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_OUTER_4W, 2, g_usw_nh_master[lchip]->ecmp_if_resolved_l2edit);
        if(DRV_FROM_TM(lchip))
        {
            uint8 loop;
            EpePktProcVxlanRsvCtl_m vxlan_rsv;
            sys_nh_vxlan_hw_profile_t* p_node;
            uint8 step = DRV_FROM_TMM(lchip) ? EpePktProcVxlanRsvCtl_g_1_rsv1_f - EpePktProcVxlanRsvCtl_g_0_rsv1_f :
                EpePktProcVxlanRsvCtl_gVxlanRsvField_1_vxlanFlags_f-EpePktProcVxlanRsvCtl_gVxlanRsvField_0_vxlanFlags_f;
            uint32 cmd = DRV_IOR(EpePktProcVxlanRsvCtl_t, DRV_ENTRY_FLAG);
            uint32 tmp;

            DRV_IOCTL(lchip, 0, cmd, &vxlan_rsv);
            for(loop=1; loop < SYS_NH_MAX_VXLAN_PROFLLE; loop++)
            {
                p_node = g_usw_nh_master[lchip]->vxlan_edit_profile + loop;
                if(DRV_FROM_TMM(lchip))
                {
                    p_node->udp_dest_port = GetEpePktProcVxlanRsvCtl(V, g_0_udpDestPort_f+step*loop, &vxlan_rsv);
                    p_node->rsv1 = GetEpePktProcVxlanRsvCtl(V, g_0_rsv1_f+step*loop, &vxlan_rsv);
                    p_node->rsv2 = GetEpePktProcVxlanRsvCtl(V, g_0_rsv2_f+step*loop, &vxlan_rsv);
                    p_node->rsv3 = GetEpePktProcVxlanRsvCtl(V, g_0_rsv3_f+step*loop, &vxlan_rsv);
                    p_node->rsv7 = GetEpePktProcVxlanRsvCtl(V, g_0_rsv7_f+step*loop, &vxlan_rsv);
                    p_node->flags = GetEpePktProcVxlanRsvCtl(V, g_0_vxlanFlags_f+step*loop, &vxlan_rsv);
                    p_node->rsv3_as_etype = GetEpePktProcVxlanRsvCtl(V, g_0_rsv3AsEType_f+step*loop, &vxlan_rsv);
                    p_node->rsv3_as_protocol = GetEpePktProcVxlanRsvCtl(V, g_0_rsv3AsProtoSel_f+step*loop, &vxlan_rsv);
                    p_node->with_policy_group = GetEpePktProcVxlanRsvCtl(V, g_0_vxlanFormatWithPolicyGroup_f+step*loop, &vxlan_rsv);
                }
                else
                {
                    tmp = GetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanReserved1_f+step*loop, &vxlan_rsv);
                    p_node->rsv1 = (tmp >> 16)&0xFF;
                    p_node->rsv2 = (tmp >> 8)&0xFF;
                    p_node->rsv3 = (tmp)&0xFF;
                    p_node->rsv7 = GetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanReserved2_f+step*loop, &vxlan_rsv);
                    p_node->flags = GetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanFlags_f+step*loop, &vxlan_rsv);
                    p_node->with_policy_group = GetEpePktProcVxlanRsvCtl(V, gVxlanRsvField_0_vxlanFormatWithPolicyGroup_f+step*loop, &vxlan_rsv);
                }
                p_node->ref_cnt = 0;
            }
        }
    }

    if(!DRV_FROM_TMM(lchip))
    {
        CTC_ERROR_DUMP(sys_usw_nh_get_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_INTERNAL, SYS_DSNH4WREG_INDEX_FOR_TWAMP_UPD_CHKSUM>>1, &dsnh8w));
        p_dsnh = (uint32*)&dsnh8w;
        if(GetDsNextHop4W(V, innerEditPtrType_f, p_dsnh))
        {
            sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_OF_6W, 1, GetDsNextHop4W(V, innerEditPtr_f, p_dsnh));
        }
    }
out:
    if (p_wb_master)
    {
        mem_free(p_wb_master);
    }

    return ret;
}

int32
_sys_usw_nh_wb_restore_ipmc_l3if(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    int32 ret = CTC_E_NONE;
    sys_wb_nh_ipmc_l3if_t wb_ipmc_l3if;
    sys_wb_nh_ipmc_l3if_t* p_wb_ipmc_l3if = &wb_ipmc_l3if;
    uint16 entry_cnt = 0;

    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_ipmc_l3if_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_L3IF);

    sal_memset(&wb_ipmc_l3if, 0, sizeof(sys_wb_nh_ipmc_l3if_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb_ipmc_l3if, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
        (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;

    if (!g_usw_nh_master[lchip]->ipmc_dsnh_offset[wb_ipmc_l3if.l3if_id] && wb_ipmc_l3if.nh_offset)
    {
        DsNextHop4W_m ds_nexthop;
        uint32 cmd = 0;

        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 1, wb_ipmc_l3if.nh_offset);
        g_usw_nh_master[lchip]->ipmc_dsnh_offset[wb_ipmc_l3if.l3if_id] = wb_ipmc_l3if.nh_offset;

        cmd = DRV_IOR(DsNextHop4W_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, wb_ipmc_l3if.nh_offset, cmd, &ds_nexthop);
        if (GetDsNextHop4W(V, outerEditPtrValid_f, &ds_nexthop) && (g_usw_nh_master[lchip]->rsv_l2edit_ptr != GetDsNextHop4W(V, u1_g4_outerEditPtr_f, &ds_nexthop)))
        {
            CTC_ERROR_DUMP(_sys_usw_nh_wb_restore_edit(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_INNER_3W, GetDsNextHop4W(V, u1_g4_outerEditPtr_f, &ds_nexthop)));
        }
    }

    if (!g_usw_nh_master[lchip]->pon_ipmc_dsnh_offset[wb_ipmc_l3if.l3if_id] && wb_ipmc_l3if.pon_nh_offset)
    {
        DsNextHop8W_m ds_nexthop;
        uint32 cmd = 0;

        sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, 1, wb_ipmc_l3if.pon_nh_offset);
        g_usw_nh_master[lchip]->pon_ipmc_dsnh_offset[wb_ipmc_l3if.l3if_id] = wb_ipmc_l3if.pon_nh_offset;

        cmd = DRV_IOR(DsNextHop8W_t, DRV_ENTRY_FLAG);
        DRV_IOCTL(lchip, wb_ipmc_l3if.pon_nh_offset, cmd, &ds_nexthop);
        if (GetDsNextHop8W(V, innerEditPtr_f, &ds_nexthop))
        {
            CTC_ERROR_DUMP(_sys_usw_nh_wb_restore_edit(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_INNER_SWAP, GetDsNextHop8W(V, innerEditPtr_f, &ds_nexthop)));
        }
    }

    CTC_WB_QUERY_ENTRY_END(p_wb_query);
 done:
    return ret;
}

STATIC int32
_sys_usw_nh_wb_restore_srh(uint8 lchip,  ctc_wb_query_t *p_wb_query, uint8 is_srh_aps)
{
    sys_nh_db_srh_t* p_db = NULL;
    sys_wb_nh_srh_t wb;
    sys_wb_nh_srh_t *p_wb = &wb;
    uint32 entry_cnt = 0;
    int32 ret = 0;
    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_srh_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_SRH);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb, 0, sizeof(sys_wb_nh_srh_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;

    if (is_srh_aps != CTC_FLAG_ISSET(p_wb->flag, SYS_NH_SRH_FLAG_APS))
    {
        continue;
    }

    p_db  = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_srh_t));
    if (NULL == p_db)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_db, 0, sizeof(sys_nh_db_srh_t));
    p_db->pd  = (sys_nh_db_srh_pdata_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_srh_pdata_t));
    if (!p_db->pd)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_db->pd, 0, sizeof(sys_nh_db_srh_pdata_t));

    _sys_usw_nh_wb_mapping_srh(lchip, p_db, p_wb, 0);
    if (NULL == ctc_hash_insert(g_usw_nh_master[lchip]->srh_id_hash, p_db))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No Memory \n");
        return CTC_E_NO_MEMORY;
    }



    if (is_srh_aps)
    {
        sys_nh_db_srh_t* p_w_srh = NULL;
        sys_nh_db_srh_t* p_p_srh = NULL;
        sys_nh_tunnel_ref_list_node_t* p_tunnel_list_node = NULL;

        CTC_ERROR_RETURN(sys_usw_nh_lkup_srh_edit(lchip, p_db->l3edit_ptr, &p_w_srh));
        CTC_ERROR_RETURN(sys_usw_nh_lkup_srh_edit(lchip, p_db->p_srh_id, &p_p_srh));
        if (!p_w_srh || !p_p_srh)
        {
            return CTC_E_NOT_EXIST;
        }

        p_tunnel_list_node = (sys_nh_tunnel_ref_list_node_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_tunnel_ref_list_node_t));
        if (p_tunnel_list_node == NULL)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;
        }
        p_tunnel_list_node->p_ref_node = p_db;
        p_tunnel_list_node->p_next = p_w_srh->pd->p_srh_list;
        p_w_srh->pd->p_srh_list = p_tunnel_list_node;

        p_tunnel_list_node = (sys_nh_tunnel_ref_list_node_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_tunnel_ref_list_node_t));
        if (p_tunnel_list_node == NULL)
        {
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
            return CTC_E_NO_MEMORY;
        }
        p_tunnel_list_node->p_ref_node = p_db;
        p_tunnel_list_node->p_next = p_p_srh->pd->p_srh_list;
        p_p_srh->pd->p_srh_list = p_tunnel_list_node;
    }

    CTC_WB_QUERY_ENTRY_END(p_wb_query);
    done:
    return ret;
}


STATIC int32
_sys_usw_nh_wb_restore_ol_tunnel(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_nh_db_ol_tunnel_t* p_db = NULL;
    sys_wb_nh_ol_tunnel_t wb;
    sys_wb_nh_ol_tunnel_t *p_wb = &wb;
    uint32 entry_cnt = 0;
    int32 ret = 0;
    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_ol_tunnel_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_OL_TUNNEL);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb, 0, sizeof(sys_wb_nh_ol_tunnel_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;
    p_db  = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_db_ol_tunnel_t));
    if (NULL == p_db)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_db, 0, sizeof(sys_nh_db_ol_tunnel_t));
    _sys_usw_nh_wb_mapping_ol_tunnel(lchip, p_db, p_wb, 0);
    if (NULL == ctc_hash_insert(g_usw_nh_master[lchip]->ol_tunnel_hash, p_db))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No Memory \n");
        return CTC_E_NO_MEMORY;
    }

    if (CTC_FLAG_ISSET(p_db->flag, SYS_NH_OL_TUNNEL_FLAG_DSFWD)&&p_db->ul_nh_en==0)
    {
        CTC_ERROR_RETURN(sys_usw_nh_offset_alloc_from_position(lchip, SYS_NH_ENTRY_TYPE_FWD1,1, p_db->ul_nhid));
    }

    CTC_WB_QUERY_ENTRY_END(p_wb_query);
    done:
    return ret;
}

STATIC int32
_sys_usw_nh_wb_restore_fp(uint8 lchip,  ctc_wb_query_t *p_wb_query)
{
    sys_nh_fp_db_t* p_db = NULL;
    sys_wb_nh_fp_t wb;
    sys_wb_nh_fp_t *p_wb = &wb;
    uint32 entry_cnt = 0;
    int32 ret = 0;
    CTC_WB_INIT_QUERY_T(p_wb_query, sys_wb_nh_fp_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_FP);
    /* set default value for new added fields, the default value may not be zeros */
    sal_memset(&wb, 0, sizeof(sys_wb_nh_fp_t));
    CTC_WB_QUERY_ENTRY_BEGIN(p_wb_query);
    sal_memcpy((uint8 *)p_wb, (uint8 *)p_wb_query->buffer + entry_cnt * (p_wb_query->key_len + p_wb_query->data_len),
               (p_wb_query->key_len + p_wb_query->data_len));
    entry_cnt++;
    p_db  = mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_nh_fp_db_t));
    if (NULL == p_db)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    sal_memset(p_db, 0, sizeof(sys_nh_fp_db_t));
    _sys_usw_nh_wb_mapping_fp(lchip, p_db, p_wb, 0);
    if (NULL == ctc_hash_insert(g_usw_nh_master[lchip]->fp_id_hash, p_db))
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No Memory \n");
        return CTC_E_NO_MEMORY;
    }
    CTC_WB_QUERY_ENTRY_END(p_wb_query);
    done:
    return ret;
}

extern int32 sys_usw_aps_wb_restore_nh(uint8 lchip);
int32
sys_usw_nh_wb_restore(uint8 lchip)
{
    ctc_wb_query_t    wb_query;
    int32 ret = 0;

   /*restore nh_matser*/
   CTC_WB_ALLOC_BUFFER(&wb_query.buffer);

   /*restore nh_matser*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_nh_master(lchip, &wb_query),ret,done);

   /*restore ipmc l3if*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_ipmc_l3if(lchip, &wb_query),ret,done);

   /*restore arp*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_arp(lchip,&wb_query),ret,done);

   /*restore mpls tunnel*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_mpls_tunnel(lchip, &wb_query, 0), ret, done);
   /*restore mpls-aps tunnel*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_mpls_tunnel(lchip,&wb_query, 1),ret,done);


   if (DRV_FROM_TMM(lchip))
   {
       /*restore srh*/
       CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_srh(lchip, &wb_query, 0), ret, done);

       /*restore srh aps*/
       CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_srh(lchip, &wb_query, 1), ret, done);

       /*restore vp tunnel*/
       CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_ol_tunnel(lchip, &wb_query), ret, done);

       /*restore fp*/
       CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_fp(lchip, &wb_query), ret, done);
   }

   /*restore  nexthop info*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_nhinfo(lchip,&wb_query),ret,done);

   /*restore  mcast info*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_mcast(lchip,&wb_query),ret,done);

  /*restore  aps nexthop info*/
    CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_aps(lchip,&wb_query),ret,done);

   /*restore  ecmp info*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_ecmp(lchip,&wb_query, 0),ret,done);

   /*restore  mcast member info*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_mcast_member(lchip,&wb_query),ret,done);

   /*restore  ecmp mem info*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_ecmp_mem(lchip,&wb_query),ret,done);

   /*restore  loop nh info*/
   CTC_ERROR_GOTO(_sys_usw_nh_wb_restore_loop_nh(lchip,&wb_query),ret,done);

   /*restore  aps module use nexthop resource*/
   CTC_ERROR_GOTO(sys_usw_aps_wb_restore_nh(lchip),ret,done);


   if (MCHIP_NH(lchip)->wb_restore)
   {
       CTC_ERROR_GOTO(MCHIP_NH(lchip)->wb_restore(lchip,&wb_query),ret,done);
   }

done:
    CTC_WB_FREE_BUFFER(wb_query.buffer);
    return ret;
}


int32
_sys_usw_nh_wb_traverse_sync_arp(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    sys_nh_db_arp_t *p_db_arp = (sys_nh_db_arp_t*)bucket_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_arp_t   *p_wb_arp;
    uint8 lchip = 0;
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb_arp = (sys_wb_nh_arp_t *)wb_data->buffer + wb_data->valid_cnt;
    lchip = wb_traverse->value1;

    _sys_usw_nh_wb_mapping_arp(lchip, p_db_arp,p_wb_arp,1);

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_traverse_sync_vni(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    sys_nh_vni_mapping_key_t *p_db_vni = (sys_nh_vni_mapping_key_t*)bucket_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_vni_fid_t   *p_wb_vni;
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb_vni = (sys_wb_nh_vni_fid_t *)wb_data->buffer + wb_data->valid_cnt;

    p_wb_vni->vn_id = p_db_vni->vn_id;
    p_wb_vni->fid = p_db_vni->fid;
    p_wb_vni->ref_cnt = p_db_vni->ref_cnt;

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_traverse_sync_ecmp_mem(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_nh_info_com_t *p_nh_info_com = (sys_nh_info_com_t*)bucket_data;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_info_ecmp_mem_t* p_wb_mem_info;
    uint32 max_buffer_cnt = wb_data->buffer_len/(wb_data->key_len + wb_data->data_len);
    sys_nh_info_ecmp_t  *p_nh_info = NULL;
    uint16 mem_idx = 0;

    if((wb_traverse->value3 && p_nh_info_com->hdr.nh_entry_type != SYS_NH_TYPE_ECMP) ||
        (!wb_traverse->value3 && p_nh_info_com->hdr.nh_entry_type == SYS_NH_TYPE_ECMP))
    {
       return CTC_E_NONE;
    }
    p_nh_info = (sys_nh_info_ecmp_t*)p_nh_info_com;

    for (mem_idx = 0; mem_idx < p_nh_info->mem_num; mem_idx++)
    {
        p_wb_mem_info = (sys_wb_nh_info_ecmp_mem_t *)wb_data->buffer + wb_data->valid_cnt;
        p_wb_mem_info->nhid = p_nh_info->hdr.nh_id;
        p_wb_mem_info->mem_index = mem_idx;
        if (mem_idx < p_nh_info->ecmp_cnt)
        {
            p_wb_mem_info->mem_nh = p_nh_info->nh_array[mem_idx];
        }

        if (mem_idx < p_nh_info->ecmp_cnt)
        {
            p_wb_mem_info->mem_nh = p_nh_info->nh_array[mem_idx];
        }

        if (++wb_data->valid_cnt == max_buffer_cnt)
        {
            ret = ctc_wb_add_entry(wb_data);
            if ( ret != CTC_E_NONE )
            {
                return ret;
            }
            wb_data->valid_cnt = 0;
        }
    }

   return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_traverse_sync_ecmp(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_nh_info_com_t *p_nh_info_com = (sys_nh_info_com_t*)bucket_data;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_info_ecmp_t   *p_wb_nh_info;
    uint32 max_buffer_cnt = wb_data->buffer_len/(wb_data->key_len + wb_data->data_len);
    uint8 lchip = wb_traverse->value1;

    if((wb_traverse->value3 && p_nh_info_com->hdr.nh_entry_type != SYS_NH_TYPE_ECMP) ||
        ((!wb_traverse->value3) && p_nh_info_com->hdr.nh_entry_type == SYS_NH_TYPE_ECMP))
    {
       return CTC_E_NONE;
    }

    p_wb_nh_info = (sys_wb_nh_info_ecmp_t *)wb_data->buffer + wb_data->valid_cnt;

    p_wb_nh_info->nh_id   = p_nh_info_com->hdr.nh_id;
    p_wb_nh_info->nh_type =  p_nh_info_com->hdr.nh_entry_type;
    p_wb_nh_info->hdr.dsnh_entry_num = p_nh_info_com->hdr.dsnh_entry_num;
    p_wb_nh_info->hdr.nh_entry_flags = p_nh_info_com->hdr.nh_entry_flags;
    p_wb_nh_info->hdr.dsfwd_offset = p_nh_info_com->hdr.dsfwd_offset;
    p_wb_nh_info->hdr.dsfwd1_offset = p_nh_info_com->hdr.dsfwd1_offset;
    p_wb_nh_info->hdr.dsnh_offset = p_nh_info_com->hdr.dsnh_offset;
    p_wb_nh_info->rsv = 0;

    _sys_usw_nh_wb_mapping_ecmp_nhinfo(lchip, p_nh_info_com, p_wb_nh_info);

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_traverse_sync_aps(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_nh_info_com_t *p_nh_info_com = (sys_nh_info_com_t*)bucket_data;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_info_aps_t   *p_wb_nh_info;
    uint32 max_buffer_cnt = wb_data->buffer_len/(wb_data->key_len + wb_data->data_len);
    sys_nh_info_aps_t  *p_nh_info = NULL;
    if(p_nh_info_com->hdr.nh_entry_type != SYS_NH_TYPE_APS)
    {
       return CTC_E_NONE;
    }
    p_wb_nh_info = (sys_wb_nh_info_aps_t *)wb_data->buffer + wb_data->valid_cnt;
    p_nh_info = (sys_nh_info_aps_t*)p_nh_info_com;
    p_wb_nh_info->nh_id   = p_nh_info_com->hdr.nh_id;
    p_wb_nh_info->nh_type =  p_nh_info_com->hdr.nh_entry_type;
    p_wb_nh_info->hdr.dsnh_entry_num = p_nh_info_com->hdr.dsnh_entry_num;
    p_wb_nh_info->hdr.nh_entry_flags = p_nh_info_com->hdr.nh_entry_flags;
    p_wb_nh_info->hdr.dsfwd_offset = p_nh_info_com->hdr.dsfwd_offset;
    p_wb_nh_info->hdr.dsfwd1_offset = p_nh_info_com->hdr.dsfwd1_offset;
    p_wb_nh_info->hdr.dsnh_offset = p_nh_info_com->hdr.dsnh_offset;
    p_wb_nh_info->w_nexthop_id =  p_nh_info->w_nexthop_id;
    p_wb_nh_info->p_nexthop_id =  p_nh_info->p_nexthop_id;
    p_wb_nh_info->aps_group_id =  p_nh_info->aps_group_id;
    p_wb_nh_info->assign_port = p_nh_info->assign_port;
    p_wb_nh_info->arp_num = p_nh_info->arp_num;
    p_wb_nh_info->aps_xcon_met = p_nh_info->aps_xcon_met;
    p_wb_nh_info->rsv = 0;


    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }
    return CTC_E_NONE;
}
int32
_sys_usw_nh_wb_traverse_sync_nhinfo(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_nh_info_com_t *p_nh_info_com = (sys_nh_info_com_t*)bucket_data;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_info_com_t   *p_wb_nh_info;
    uint32 max_buffer_cnt = wb_data->buffer_len/(wb_data->key_len + wb_data->data_len);
    uint8 lchip = wb_traverse->value1;

    if((wb_traverse->value3 && p_nh_info_com->hdr.nh_entry_type != SYS_NH_TYPE_ECMP)
   	|| (!wb_traverse->value3 && p_nh_info_com->hdr.nh_entry_type == SYS_NH_TYPE_ECMP)
   	|| (wb_traverse->value2 && p_nh_info_com->hdr.nh_entry_type != SYS_NH_TYPE_MCAST)
   	|| (!wb_traverse->value2 && p_nh_info_com->hdr.nh_entry_type == SYS_NH_TYPE_MCAST)
   	|| p_nh_info_com->hdr.nh_entry_type == SYS_NH_TYPE_APS)
    {
       return CTC_E_NONE;
    }

    if (p_nh_info_com->hdr.nh_entry_type == SYS_NH_TYPE_MCAST )
    {
        sys_nh_info_mcast_t* p_mcast_db = (sys_nh_info_mcast_t*)p_nh_info_com;
        if (CTC_FLAG_ISSET(p_nh_info_com->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_MCAST_PROFILE)
            || (CTC_FLAG_ISSET(p_mcast_db->mcast_flag, SYS_NH_INFO_MCAST_FLAG_LOGIC_REP_LIST_EN) && !DRV_FROM_TMM(lchip)))
        {
            if (wb_traverse->value2 == 1)
            {
                CTC_ERROR_RETURN(_sys_usw_nh_wb_traverse_sync_mcast(bucket_data, 0, wb_traverse->data));
            }
            else
            {
                CTC_ERROR_RETURN(_sys_usw_nh_wb_traverse_sync_mcast_mem(bucket_data, 0, wb_traverse));
            }
        }
        return CTC_E_NONE;
    }

    p_wb_nh_info = (sys_wb_nh_info_com_t *)wb_data->buffer + wb_data->valid_cnt;

    p_wb_nh_info->nh_id   = p_nh_info_com->hdr.nh_id;
    p_wb_nh_info->nh_type =  p_nh_info_com->hdr.nh_entry_type;
    p_wb_nh_info->hdr.dsnh_entry_num = p_nh_info_com->hdr.dsnh_entry_num;
    p_wb_nh_info->hdr.nh_entry_flags = p_nh_info_com->hdr.nh_entry_flags;
    p_wb_nh_info->hdr.dsfwd_offset = p_nh_info_com->hdr.dsfwd_offset;
    p_wb_nh_info->hdr.dsfwd1_offset = p_nh_info_com->hdr.dsfwd1_offset;
    p_wb_nh_info->hdr.dsnh_offset = p_nh_info_com->hdr.dsnh_offset;

    switch(p_wb_nh_info->nh_type)
    {
        case SYS_NH_TYPE_IPUC:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_ipuc_nhinfo(wb_traverse->value1,p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_BRGUC:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_brguc_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_MISC:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_misc_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_TOCPU:
        case SYS_NH_TYPE_DROP:
        case SYS_NH_TYPE_UNROV:
        case SYS_NH_TYPE_ILOOP:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_special_nhinfo(p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_RSPAN:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_rspan_nhinfo(p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_IP_TUNNEL:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_ip_tunnel_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_WLAN_TUNNEL:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_wlan_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_SRV6:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_srv6_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_OVERLAY_VNI:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_ol_vni_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_OVERLAY:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_overlay_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_MPLS:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_mpls_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        case SYS_NH_TYPE_TRILL:
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_trill_nhinfo(lchip, p_nh_info_com, p_wb_nh_info, 1));
            break;
        default:
            return CTC_E_NONE;
            break;
    }

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_traverse_sync_mcast_mem(void *data,uint32 vec_index, void *user_data)
{
    sys_nh_info_mcast_t* p_nh_info = (sys_nh_info_mcast_t*)data;
    sys_traverse_t* wb_traverse = (sys_traverse_t*)user_data;
    ctc_wb_data_t* wb_data = (ctc_wb_data_t*)wb_traverse->data;
    sys_wb_nh_info_mcast_mem_t   wb_mem_info = {0};
    sys_nh_mcast_meminfo_t* p_meminfo = NULL;
    ctc_list_pointer_node_t* p_list_node = NULL;
    uint16 loop = 0, loop_cnt = 0;
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);
    ctc_list_pointer_node_t* p_logic_node = NULL;
    sys_nh_mcast_meminfo_t* p_logic_rep_node = NULL;

    CTC_LIST_POINTER_LOOP(p_list_node, &(p_nh_info->p_mem_list))
    {
        p_meminfo = _ctc_container_of(p_list_node, sys_nh_mcast_meminfo_t, list_head);
        wb_mem_info.basic_met_offset = p_nh_info->basic_met_offset;
        wb_mem_info.dsmet_offset = p_meminfo->dsmet.dsmet_offset;
        wb_mem_info.next_dsmet_offset = p_meminfo->dsmet.next_dsmet_offset;
        wb_mem_info.flag = p_meminfo->dsmet.flag;
        wb_mem_info.logic_port = p_meminfo->dsmet.logic_port;
        wb_mem_info.fid = p_meminfo->dsmet.fid;

        wb_mem_info.dsnh_offset = p_meminfo->dsmet.dsnh_offset;
        wb_mem_info.ref_nhid = p_meminfo->dsmet.ref_nhid;
        wb_mem_info.ucastid = p_meminfo->dsmet.ucastid;
        wb_mem_info.replicate_num = p_meminfo->dsmet.replicate_num;
        wb_mem_info.free_dsnh_offset_cnt = p_meminfo->dsmet.free_dsnh_offset_cnt;
        wb_mem_info.member_type = p_meminfo->dsmet.member_type;
        wb_mem_info.port_type = p_meminfo->dsmet.port_type;
        wb_mem_info.entry_type = p_meminfo->dsmet.entry_type;
        wb_mem_info.mcast_nhid = p_nh_info->hdr.nh_id;
        wb_mem_info.cvid = p_meminfo->dsmet.cvid;

        if (wb_mem_info.member_type == SYS_NH_PARAM_IPMC_MEM_LOCAL_LOGIC_REP)
        {
            loop_cnt = p_meminfo->dsmet.replicate_num + 1;
        }
        else
        {
            loop_cnt  = 1;
        }

        if (CTC_FLAG_ISSET(p_meminfo->dsmet.flag, SYS_NH_DSMET_FLAG_LOGIC_REPLI_EN) && DRV_FROM_TMM(wb_traverse->value1))
        {
            sal_memcpy( (uint8*)wb_data->buffer + wb_data->valid_cnt * sizeof(sys_wb_nh_info_mcast_mem_t), (uint8*)&wb_mem_info, sizeof(sys_wb_nh_info_mcast_mem_t));

            if (++wb_data->valid_cnt ==  max_buffer_cnt)
            {
                if (ctc_wb_add_entry(wb_data) < 0)
                {
#ifndef CTC_SHELL_DEBUG_ON
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No resource in ASIC \n");
#endif
                    return CTC_E_NO_RESOURCE;
                }
                wb_data->valid_cnt = 0;
            }

            CTC_LIST_POINTER_LOOP(p_logic_node, &p_meminfo->dsmet.logic_rep_list)
            {
                p_logic_rep_node = _ctc_container_of(p_logic_node, sys_nh_mcast_meminfo_t, list_head);
                wb_mem_info.dsmet_offset = p_logic_rep_node->dsmet.dsmet_offset;
                wb_mem_info.next_dsmet_offset = p_logic_rep_node->dsmet.next_dsmet_offset;
                wb_mem_info.flag = p_logic_rep_node->dsmet.flag;
                wb_mem_info.logic_port = p_logic_rep_node->dsmet.logic_port;
                wb_mem_info.fid = p_logic_rep_node->dsmet.fid;
                wb_mem_info.dsnh_offset = p_logic_rep_node->dsmet.dsnh_offset;
                wb_mem_info.ref_nhid = p_logic_rep_node->dsmet.ref_nhid;
                wb_mem_info.ucastid = p_logic_rep_node->dsmet.ucastid;
                wb_mem_info.replicate_num = p_logic_rep_node->dsmet.replicate_num;
                wb_mem_info.free_dsnh_offset_cnt = p_logic_rep_node->dsmet.free_dsnh_offset_cnt;
                wb_mem_info.member_type = p_logic_rep_node->dsmet.member_type;
                wb_mem_info.port_type = p_logic_rep_node->dsmet.port_type;
                wb_mem_info.entry_type = p_logic_rep_node->dsmet.entry_type;
                wb_mem_info.mcast_nhid = p_nh_info->hdr.nh_id;

                sal_memcpy( (uint8*)wb_data->buffer + wb_data->valid_cnt * sizeof(sys_wb_nh_info_mcast_mem_t), (uint8*)&wb_mem_info, sizeof(sys_wb_nh_info_mcast_mem_t));
                if (++wb_data->valid_cnt ==  max_buffer_cnt)
                {
                    if (ctc_wb_add_entry(wb_data) < 0)
                    {
#ifndef CTC_SHELL_DEBUG_ON
                        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No resource in ASIC \n");
#endif
                        return CTC_E_NO_RESOURCE;
                    }
                    wb_data->valid_cnt = 0;
                }
            }
            continue;
        }

        for (loop = 0; loop < loop_cnt; loop++)
        {
            if (wb_mem_info.member_type == SYS_NH_PARAM_IPMC_MEM_LOCAL_LOGIC_REP && (p_meminfo->dsmet.replicate_num > 0))
            {
                wb_mem_info.vid =  p_meminfo->dsmet.vid_list[loop];
            }
            else
            {
                wb_mem_info.vid = p_meminfo->dsmet.vid;
            }
            sal_memcpy( (uint8*)wb_data->buffer + wb_data->valid_cnt * sizeof(sys_wb_nh_info_mcast_mem_t),
                       (uint8*)&wb_mem_info, sizeof(sys_wb_nh_info_mcast_mem_t));

            if (++wb_data->valid_cnt ==  max_buffer_cnt)
            {
                if (ctc_wb_add_entry(wb_data) < 0)
                {
#ifndef CTC_SHELL_DEBUG_ON
                    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No resource in ASIC \n");
#endif
                    return CTC_E_NO_RESOURCE;
                }
                wb_data->valid_cnt = 0;
            }
        }
    }

    if(CTC_FLAG_ISSET(p_nh_info->mcast_flag, SYS_NH_INFO_MCAST_FLAG_MEM_PROFILE))
    {
        sal_memset(&wb_mem_info, 0, sizeof(sys_wb_nh_info_mcast_mem_t));

        wb_mem_info.basic_met_offset = p_nh_info->basic_met_offset;
        wb_mem_info.mcast_nhid = p_nh_info->hdr.nh_id;
        wb_mem_info.dsmet_offset = p_nh_info->profile_met_offset;
        wb_mem_info.ref_nhid = p_nh_info->profile_nh_id;
        wb_mem_info.member_type = SYS_NH_PARAM_MCAST_MEM_LOCAL_WITH_NH;

        sal_memcpy( (uint8*)wb_data->buffer + wb_data->valid_cnt * sizeof(sys_wb_nh_info_mcast_mem_t),
                       (uint8*)&wb_mem_info, sizeof(sys_wb_nh_info_mcast_mem_t));

        if (++wb_data->valid_cnt ==  max_buffer_cnt)
        {
            if (ctc_wb_add_entry(wb_data) < 0)
            {
#ifndef CTC_SHELL_DEBUG_ON
                SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No resource in ASIC \n");
#endif
                return CTC_E_NO_RESOURCE;
            }
            wb_data->valid_cnt = 0;
        }
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_sync_loop_nh(uint8 lchip,  ctc_wb_data_t *wb_data)
{
    ctc_slistnode_t* slist_node = NULL;
    sys_nh_eloop_node_t* p_eloop_node = NULL;
    sys_wb_nh_loop_nh_t wb;

    CTC_SLIST_LOOP(g_usw_nh_master[lchip]->eloop_list, slist_node)
    {
        p_eloop_node = _ctc_container_of(slist_node, sys_nh_eloop_node_t, head);
        wb.edit_ptr =  p_eloop_node->edit_ptr;
        wb.is_l2edit = p_eloop_node->is_l2edit ;
        wb.nhid = p_eloop_node->nhid ;
        wb.ref_cnt = p_eloop_node->ref_cnt ;
        wb.lb_with_ldp = p_eloop_node->lb_with_ldp;
        wb.rsv = 0;
        sal_memcpy( (uint8*)wb_data->buffer + wb_data->valid_cnt * sizeof(sys_wb_nh_loop_nh_t), (uint8*)&wb, sizeof(sys_wb_nh_loop_nh_t));
        wb_data->valid_cnt++;
    }
   if (wb_data->valid_cnt > 0)
   {
      CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
      wb_data->valid_cnt = 0;
   }

    return CTC_E_NONE;
}

int32
_sys_usw_nh_wb_traverse_sync_mcast(void *data,uint32 vec_index, void *user_data)
{
    sys_nh_info_mcast_t* p_nh_info = (sys_nh_info_mcast_t*)data;
    ctc_wb_data_t* wb_data = (ctc_wb_data_t*)user_data;
    sys_wb_nh_info_mcast_t   wb_mcast_info = {0};
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    wb_mcast_info.hdr.dsnh_entry_num = p_nh_info->hdr.dsnh_entry_num;
    wb_mcast_info.hdr.nh_entry_flags = p_nh_info->hdr.nh_entry_flags;
    wb_mcast_info.hdr.dsfwd_offset = p_nh_info->hdr.dsfwd_offset;
    wb_mcast_info.hdr.dsnh_offset = p_nh_info->hdr.dsnh_offset;
    wb_mcast_info.profile_met_offset = p_nh_info->profile_met_offset;
    wb_mcast_info.profile_nh_id = p_nh_info->profile_nh_id;
    wb_mcast_info.nh_id  = p_nh_info->hdr.nh_id;
    wb_mcast_info.basic_met_offset = p_nh_info->basic_met_offset;
    wb_mcast_info.physical_replication_num = p_nh_info->physical_replication_num;
    wb_mcast_info.mcast_flag = p_nh_info->mcast_flag;
    wb_mcast_info.rsv = 0;
    wb_mcast_info.rsv1 = 0;
    wb_mcast_info.hdr.dsnh_offset = p_nh_info->stats_ptr;
    wb_mcast_info.pp_bmp = p_nh_info->pp_bmp;
    sal_memcpy( (uint8*)wb_data->buffer + wb_data->valid_cnt * sizeof(sys_wb_nh_info_mcast_t),
               (uint8*)&wb_mcast_info, sizeof(sys_wb_nh_info_mcast_t));

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        if ( ctc_wb_add_entry(wb_data) < 0 )
        {
            return CTC_E_NO_RESOURCE;
        }
        wb_data->valid_cnt = 0;
    }
    return CTC_E_NONE;
}


int32
_sys_usw_nh_wb_traverse_sync_mpls_tunnel(void *data,uint32 vec_index, void *user_data)
{
    uint32 max_entry_cnt = 0;
    sys_nh_db_mpls_tunnel_t *p_tunnel = (sys_nh_db_mpls_tunnel_t *)data;
    sys_wb_nh_mpls_tunnel_t  *p_wb_tunnel;
    sys_traverse_t *traversal_data = (sys_traverse_t *)user_data;
    ctc_wb_data_t *wb_data = (ctc_wb_data_t *)traversal_data->data;
    uint8 lchip = (uint8)traversal_data->value1;
    uint8 lsp_cnt = 1;
    uint8 spme_cnt = 1;
    uint8 lsp_idx = 0;
    uint8 spme_idx = 0;

    max_entry_cnt =  wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);
    if (CTC_FLAG_ISSET(p_tunnel->flag, SYS_NH_MPLS_TUNNEL_FLAG_APS))
    {
        lsp_cnt = 2;
     }

    for (lsp_idx =0; lsp_idx < lsp_cnt; lsp_idx++)
    {
        for (spme_idx = 0; spme_idx < spme_cnt; spme_idx++)
        {
            p_wb_tunnel = (sys_wb_nh_mpls_tunnel_t *)wb_data->buffer + wb_data->valid_cnt;
            sal_memset(p_wb_tunnel, 0, sizeof(sys_wb_nh_mpls_tunnel_t));
            CTC_ERROR_RETURN(_sys_usw_nh_wb_mapping_mpls_tunnel(lchip, p_tunnel, p_wb_tunnel, 1, lsp_idx, spme_idx));

            if (++wb_data->valid_cnt == max_entry_cnt)
            {
                CTC_ERROR_RETURN(ctc_wb_add_entry(wb_data));
                wb_data->valid_cnt = 0;
            }
        }

    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_traverse_sync_srh(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    sys_nh_db_srh_t *p_db = (sys_nh_db_srh_t*)bucket_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_srh_t   *p_wb;
    uint8 lchip = 0;
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb = (sys_wb_nh_srh_t *)wb_data->buffer + wb_data->valid_cnt;
    lchip = wb_traverse->value1;

    _sys_usw_nh_wb_mapping_srh(lchip, p_db,p_wb,1);

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_wb_traverse_sync_ol_tunnel(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    sys_nh_db_ol_tunnel_t *p_db = (sys_nh_db_ol_tunnel_t*)bucket_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_ol_tunnel_t   *p_wb;
    uint8 lchip = 0;
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb = (sys_wb_nh_ol_tunnel_t *)wb_data->buffer + wb_data->valid_cnt;
    lchip = wb_traverse->value1;

    _sys_usw_nh_wb_mapping_ol_tunnel(lchip, p_db,p_wb,1);

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_nh_wb_traverse_sync_fp(void* bucket_data, void* user_data)
{
    int32 ret;
    sys_traverse_t *wb_traverse = (sys_traverse_t*)user_data;
    sys_nh_fp_db_t *p_db = (sys_nh_fp_db_t*)bucket_data;
    ctc_wb_data_t *wb_data = wb_traverse->data;
    sys_wb_nh_fp_t   *p_wb;
    uint8 lchip = 0;
    uint32 max_buffer_cnt = wb_data->buffer_len / (wb_data->key_len + wb_data->data_len);

    p_wb = (sys_wb_nh_fp_t *)wb_data->buffer + wb_data->valid_cnt;
    lchip = wb_traverse->value1;

    _sys_usw_nh_wb_mapping_fp(lchip, p_db,p_wb,1);

    if (++wb_data->valid_cnt ==  max_buffer_cnt)
    {
        ret = ctc_wb_add_entry(wb_data);
        if ( ret != CTC_E_NONE )
        {
           return ret;
        }
        wb_data->valid_cnt = 0;
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_wb_sync(uint8 lchip, uint32 app_id)
{
    int32 ret = CTC_E_NONE;
    ctc_wb_data_t wb_data = {0};
    sys_wb_nh_master_t* p_wb_nh_master = NULL;
    sys_traverse_t  wb_nh_traverse  = {0};
    sys_traverse_t  wb_arp_traverse = {0};
    sys_traverse_t  wb_vni_traverse = {0};
    sys_traverse_t  wb_traverse     = {0};



    p_wb_nh_master = (sys_wb_nh_master_t*)mem_malloc(MEM_NEXTHOP_MODULE, sizeof(sys_wb_nh_master_t));
    if (NULL == p_wb_nh_master)
    {
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " No memory \n");
        return CTC_E_NO_MEMORY;
    }
    CTC_WB_ALLOC_BUFFER(&wb_data.buffer);
    sal_memset(p_wb_nh_master, 0, sizeof(sys_wb_nh_master_t));
    SYS_NH_LOCK;
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_MASTER)
    {
        /*syncup  nh_matser*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_master_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER);
        p_wb_nh_master->lchip = lchip;
        p_wb_nh_master->max_external_nhid = g_usw_nh_master[lchip]->max_external_nhid;
        p_wb_nh_master->max_tunnel_id = g_usw_nh_master[lchip]->max_tunnel_id;
        p_wb_nh_master->max_srh_id = g_usw_nh_master[lchip]->max_srh_id;
        p_wb_nh_master->max_ecmp = g_usw_nh_master[lchip]->max_ecmp;
        p_wb_nh_master->max_ecmp_group_num = g_usw_nh_master[lchip]->max_ecmp_group_num;
        p_wb_nh_master->ipmc_logic_replication = g_usw_nh_master[lchip]->ipmc_logic_replication;
        p_wb_nh_master->ecmp_if_resolved_l2edit = g_usw_nh_master[lchip]->ecmp_if_resolved_l2edit;
        p_wb_nh_master->reflective_resolved_dsfwd_offset = g_usw_nh_master[lchip]->reflective_resolved_dsfwd_offset;
        p_wb_nh_master->pkt_nh_edit_mode = g_usw_nh_master[lchip]->pkt_nh_edit_mode;
        p_wb_nh_master->reflective_brg_en = g_usw_nh_master[lchip]->reflective_brg_en;
        p_wb_nh_master->version = SYS_WB_VERSION_NEXTHOP;
        p_wb_nh_master->udf_profile_bitmap = g_usw_nh_master[lchip]->udf_profile_bitmap;
        p_wb_nh_master->efd_nh_id = g_usw_nh_master[lchip]->efd_nh_id;
        p_wb_nh_master->rsv_l2edit_ptr = g_usw_nh_master[lchip]->rsv_l2edit_ptr;
        p_wb_nh_master->rsv_l3edit_for_nsh = g_usw_nh_master[lchip]->rsv_l3edit_for_nsh;
        p_wb_nh_master->srv6_resolved_l2edit = g_usw_nh_master[lchip]->srv6_resolved_l2edit;
        p_wb_nh_master->rsv_l3edit_for_igs_edit = g_usw_nh_master[lchip]->rsv_l3edit_for_igs_edit;
        p_wb_nh_master->rsv_xedit_for_igs_edit = g_usw_nh_master[lchip]->rsv_xedit_for_igs_edit;
        p_wb_nh_master->rsv_nh_ptr = g_usw_nh_master[lchip]->rsv_nh_ptr;
        p_wb_nh_master->outer_l2_ptr = g_usw_nh_master[lchip]->outer_l2_ptr;
        p_wb_nh_master->outer_l2_ptr_ref = g_usw_nh_master[lchip]->outer_l2_ptr_ref;
        p_wb_nh_master->vxlan_mode = g_usw_nh_master[lchip]->vxlan_mode;
        p_wb_nh_master->hecmp_mem_num = g_usw_nh_master[lchip]->hecmp_mem_num;
        p_wb_nh_master->rsv_iloop_nh = g_usw_nh_master[lchip]->rsv_iloop_nh;
        p_wb_nh_master->bpe_mc_en = g_usw_nh_master[lchip]->bpe_mc_en;
        p_wb_nh_master->gem_port_edit_num = g_usw_nh_master[lchip]->gem_port_edit_num;
        p_wb_nh_master->gem_port_edit_base = g_usw_nh_master[lchip]->gem_port_edit_base;
        sal_memcpy(p_wb_nh_master->pon_mc_dsnh, g_usw_nh_master[lchip]->pon_mc_dsnh, sizeof(uint32)*SYS_NH_PON_MC_DSNH_NUM);
        sal_memcpy(p_wb_nh_master->udf_ether_type, g_usw_nh_master[lchip]->udf_ether_type, sizeof(g_usw_nh_master[lchip]->udf_ether_type));
        sal_memcpy(p_wb_nh_master->cw_ref_cnt, g_usw_nh_master[lchip]->cw_ref_cnt,  SYS_NH_CW_NUM*sizeof(uint16));

        sal_memcpy((uint8*)wb_data.buffer, (uint8*)p_wb_nh_master, sizeof(sys_wb_nh_master_t));

        wb_data.valid_cnt = 1;
        CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_MCAST_L3IF)
    {
        uint16 index = 0;
        uint32 max_cnt = 0;
        sys_wb_nh_ipmc_l3if_t* p_ipmc_l3if = NULL;
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_ipmc_l3if_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_L3IF);
        max_cnt = wb_data.buffer_len/(wb_data.key_len + wb_data.data_len);
        for (index = 0; index < MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM); index++)
        {
            if (g_usw_nh_master[lchip]->ipmc_dsnh_offset[index] ||  g_usw_nh_master[lchip]->pon_ipmc_dsnh_offset[index])
            {
                p_ipmc_l3if = (sys_wb_nh_ipmc_l3if_t*)wb_data.buffer + wb_data.valid_cnt;
                p_ipmc_l3if->l3if_id = index;
                p_ipmc_l3if->nh_offset = g_usw_nh_master[lchip]->ipmc_dsnh_offset[index];
                p_ipmc_l3if->pon_nh_offset =g_usw_nh_master[lchip]->pon_ipmc_dsnh_offset[index];
                if (++wb_data.valid_cnt ==  max_cnt)
                {
                    ret = ctc_wb_add_entry(&wb_data);
                    if ( ret != CTC_E_NONE )
                    {
                       SYS_NH_UNLOCK;
                       return ret;
                    }
                    wb_data.valid_cnt = 0;
                }
            }
        }
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }

        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_L3IF);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_ARP)
    {

       CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_arp_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ARP);
        /*sync arp*/
        wb_arp_traverse.data = &wb_data;
        wb_arp_traverse.value1 = lchip;
        wb_arp_traverse.value2 = 0;
        wb_arp_traverse.value3 = 0;

        ctc_hash_traverse(g_usw_nh_master[lchip]->arp_id_hash, _sys_usw_nh_wb_traverse_sync_arp, &wb_arp_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ARP);
    }
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_INFO_COM)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_info_com_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM);
        /*sync nexthop info*/
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value1 = lchip;
        wb_nh_traverse.value2 = 0;
        wb_nh_traverse.value3 = 0;

        ctc_hash_traverse(g_usw_nh_master[lchip]->nhid_hash, _sys_usw_nh_wb_traverse_sync_nhinfo, &wb_nh_traverse);

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_ECMP)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_info_ecmp_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP);
        /*sync ecmp nexthop*/
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value1 = lchip;
        wb_nh_traverse.value2 = 0;
        wb_nh_traverse.value3 = 1;
        ctc_hash_traverse(g_usw_nh_master[lchip]->nhid_hash, _sys_usw_nh_wb_traverse_sync_ecmp, &wb_nh_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_ECMP_MEM)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_info_ecmp_mem_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP_MEM);
        /*sync ecmp nexthop*/
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value1 = lchip;
        wb_nh_traverse.value2 = 0;
        wb_nh_traverse.value3 = 2;
        ctc_hash_traverse(g_usw_nh_master[lchip]->nhid_hash, _sys_usw_nh_wb_traverse_sync_ecmp_mem, &wb_nh_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }

        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP_MEM);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_INFO_MCAST)
    {

        /*sync mcast*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_info_mcast_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_MCAST);
        ctc_vector_traverse2(g_usw_nh_master[lchip]->mcast_group_vec, 0, _sys_usw_nh_wb_traverse_sync_mcast, &wb_data);

        /*sync mcast profile*/
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value1 = lchip;
        wb_nh_traverse.value2 = 1;
        wb_nh_traverse.value3 = 0;
        ctc_hash_traverse(g_usw_nh_master[lchip]->nhid_hash, _sys_usw_nh_wb_traverse_sync_nhinfo, &wb_nh_traverse);

        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_MCAST);

    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_MCAST_MEM)
    {
        /*sync mcast member*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_info_mcast_mem_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_MEM);
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value1 = lchip;
        wb_nh_traverse.value2 = 0;
        wb_nh_traverse.value3 = 0;
        ctc_vector_traverse2(g_usw_nh_master[lchip]->mcast_group_vec, 0, _sys_usw_nh_wb_traverse_sync_mcast_mem, &wb_nh_traverse);

        /*sync mcast profile member*/
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value1 = lchip;
        wb_nh_traverse.value2 = 2;
        wb_nh_traverse.value3 = 0;
        ctc_hash_traverse(g_usw_nh_master[lchip]->nhid_hash, _sys_usw_nh_wb_traverse_sync_nhinfo, &wb_nh_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_MEM);

    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_MPLS_TUNNEL)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_mpls_tunnel_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MPLS_TUNNEL);
        /*sync mpls tunnel info*/
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value2 = 1;
        wb_nh_traverse.value3 = 0;
         ctc_vector_traverse2(g_usw_nh_master[lchip]->tunnel_id_vec, 0, _sys_usw_nh_wb_traverse_sync_mpls_tunnel, &wb_nh_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MPLS_TUNNEL);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_VNI)
    {
        /*sync vni*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_vni_fid_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_VNI);

        wb_vni_traverse.data = &wb_data;
        wb_vni_traverse.value1 = lchip;
        wb_vni_traverse.value2 = 0;
        wb_vni_traverse.value3 = 0;
        ctc_hash_traverse(g_usw_nh_master[lchip]->vxlan_vni_hash, _sys_usw_nh_wb_traverse_sync_vni, &wb_vni_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_VNI);
    }


    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_APS)
    {
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_info_aps_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_APS);
        wb_nh_traverse.data = &wb_data;
        wb_nh_traverse.value1 = lchip;
        ctc_hash_traverse(g_usw_nh_master[lchip]->nhid_hash, _sys_usw_nh_wb_traverse_sync_aps, &wb_nh_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_APS);
    }

    if ((app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_OL_TUNNEL) &&
        (DRV_FROM_TMM(lchip) || (DRV_IS_TSINGMA(lchip) && g_usw_nh_master[lchip]->bind_ldp)))
    {
        /*sync ol tunnel*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_ol_tunnel_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_OL_TUNNEL);
        sal_memset(&wb_traverse, 0, sizeof(wb_traverse));
        wb_traverse.data = &wb_data;
        wb_traverse.value1 = lchip;
        ctc_hash_traverse(g_usw_nh_master[lchip]->ol_tunnel_hash, _sys_usw_nh_wb_traverse_sync_ol_tunnel, &wb_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_OL_TUNNEL);
    }

    if ((app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_SRH) && DRV_FROM_TMM(lchip))
    {
        /*sync srh*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_srh_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_SRH);
        sal_memset(&wb_traverse, 0, sizeof(wb_traverse));
        wb_traverse.data = &wb_data;
        wb_traverse.value1 = lchip;
        ctc_hash_traverse(g_usw_nh_master[lchip]->srh_id_hash, _sys_usw_nh_wb_traverse_sync_srh, &wb_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }
        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_SRH);
    }

    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_FP)
    {
        /*sync fp*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_fp_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_FP);
        sal_memset(&wb_traverse, 0, sizeof(wb_traverse));
        wb_traverse.data = &wb_data;
        wb_traverse.value1 = lchip;
        ctc_hash_traverse(g_usw_nh_master[lchip]->fp_id_hash, _sys_usw_nh_wb_traverse_sync_fp, &wb_traverse);
        if (wb_data.valid_cnt > 0)
        {
            CTC_ERROR_GOTO(ctc_wb_add_entry(&wb_data), ret, done);
            wb_data.valid_cnt = 0;
        }

        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_FP);
    }
    if (app_id == 0 || CTC_WB_SUBID(app_id) == SYS_WB_APPID_NH_SUBID_LOOP_NH )
    {
        /*sync fp*/
        CTC_WB_INIT_DATA_T((&wb_data), sys_wb_nh_loop_nh_t, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_LOOP_NH);
         _sys_usw_nh_wb_sync_loop_nh(lchip,&wb_data);

        CTC_WB_SYNC_END_DATA(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_LOOP_NH);
    }

    if (MCHIP_NH(lchip)->wb_sync)
    {
        CTC_ERROR_GOTO(MCHIP_NH(lchip)->wb_sync(lchip,app_id,&wb_data), ret, done);
    }

    done:
    SYS_NH_UNLOCK;
    CTC_WB_FREE_BUFFER(wb_data.buffer);
    if (p_wb_nh_master)
    {
        mem_free(p_wb_nh_master);
    }

    return ret;
}

STATIC int32
_sys_usw_nh_wb_init(uint8 lchip)
{
    ctc_wb_appid_t  appid;
    sal_memset(&appid, 0, sizeof(appid));

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER) ;
    appid.entry_num = 1;
    appid.entry_size  = sizeof(sys_wb_nh_master_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_COM) ;
    appid.entry_num = g_usw_nh_master[lchip]->max_external_nhid + g_usw_nh_master[lchip]->max_glb_met_offset
        + 2*SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_RCHIP_PORT) + 1024 + SYS_WB_NH_SUBID_VNI_NUM;
    appid.entry_size  = sizeof(sys_wb_nh_info_com_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_MPLS))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MPLS_TUNNEL) ;
        appid.entry_num = g_usw_nh_master[lchip]->max_tunnel_id+1;
        appid.entry_size  = sizeof(sys_wb_nh_mpls_tunnel_t);
        appid.rt_en = 0;
        ctc_wb_add_appid(lchip, &appid);
    }

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP) ;
    appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, DsEcmpGroup_t);
    appid.entry_size  = sizeof(sys_wb_nh_info_ecmp_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_INFO_MCAST) ;
    appid.entry_num =  g_usw_nh_master[lchip]->max_glb_met_offset;
    appid.entry_size  = sizeof(sys_wb_nh_info_mcast_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ARP) ;
    appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_IPUC_HOST)+SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_IPUC_ND);
    appid.entry_size  = sizeof(sys_wb_nh_arp_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_OVERLAY))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_VNI) ;
        appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, DsEgressVsi_t)*4;
        appid.entry_size  = sizeof(sys_wb_nh_vni_fid_t);
        appid.rt_en = 0;
        ctc_wb_add_appid(lchip, &appid);
    }

    if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_APS))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_APS) ;
        appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_APS);
        appid.entry_size  = sizeof(sys_wb_nh_info_aps_t);
        appid.rt_en = 0;
        ctc_wb_add_appid(lchip, &appid);
    }

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_ECMP_MEM) ;
    appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, DsEcmpMember_t)*4;
    appid.entry_size  = sizeof(sys_wb_nh_info_ecmp_mem_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_MEM) ;
    if (DRV_FROM_AT(lchip))
    {
        appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, DsMetEntry1X_t);
    }
    else
    {
        appid.entry_num = DRV_TABLE_MAX_INDEX(lchip, DsMetEntry3W_t);
    }
    appid.entry_num = appid.entry_num / 4;
    appid.entry_size  = sizeof(sys_wb_nh_info_mcast_mem_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MCAST_L3IF) ;
    appid.entry_num = MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM);
    appid.entry_size  = sizeof(sys_wb_nh_ipmc_l3if_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    if (DRV_FROM_TMM(lchip))
    {
        if (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_SRV6))
        {
            appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_SRH) ;
            appid.entry_num = g_usw_nh_master[lchip]->max_srh_id + 1;
            appid.entry_size  = sizeof(sys_wb_nh_srh_t);
            appid.rt_en = 0;
            ctc_wb_add_appid(lchip, &appid);
        }
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_FP) ;
        appid.entry_num = SYS_NH_FP_NUM;
        appid.entry_size  = sizeof(sys_wb_nh_fp_t);
        appid.rt_en = 0;
        ctc_wb_add_appid(lchip, &appid);
    }

    if((DRV_FROM_TMM(lchip) || (DRV_IS_TSINGMA(lchip) && g_usw_nh_master[lchip]->bind_ldp)) && (MCHIP_FEATURE_INIT(lchip, CTC_FEATURE_OVERLAY)))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_OL_TUNNEL) ;
        appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_TUNNEL);
        appid.entry_size  = sizeof(sys_wb_nh_ol_tunnel_t);
        appid.rt_en = 0;
        ctc_wb_add_appid(lchip, &appid);
    }
    appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_LOOP_NH) ;
    appid.entry_num =1024;
    appid.entry_size  = sizeof(sys_wb_nh_loop_nh_t);
    appid.rt_en = 0;
    ctc_wb_add_appid(lchip, &appid);

    if (DRV_FROM_AT(lchip))
    {
        appid.app_id = lchip << 16 | CTC_WB_APPID(CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_NSH) ;
        appid.entry_num = SYS_FTM_SPEC(lchip, CTC_FTM_SPEC_NSH);
        appid.entry_size  = sizeof(sys_wb_nh_nsh_t);
        appid.rt_en = 0;
        CTC_ERROR_RETURN(ctc_wb_add_appid(lchip, &appid));
    }

    return CTC_E_NONE;
}


STATIC int32
_sys_usw_nexthop_traverse_fprintf_vprof_pool(void* node, sys_dump_db_traverse_param_t* user_date)
{
    sal_file_t                  p_file      = (sal_file_t)user_date->value0;
    sys_dsl2edit_vlan_edit_t*   p_vprof_db =  NULL;
    uint32*                     cnt         = (uint32 *)(user_date->value1);
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = user_date->lchip;
#endif
    p_vprof_db = (sys_dsl2edit_vlan_edit_t*)((ctc_spool_node_t*)node)->data;
    SYS_DUMP_DB_LOG(p_file, "%-10s:%-5u,     %-10s:%-5u\n","Node", *cnt, "refcnt", ((ctc_spool_node_t*)node)->ref_cnt);
    SYS_DUMP_DB_LOG(p_file, "%-10s\n","----------------------------------------");
    SYS_DUMP_DB_LOG(p_file, "  %-20s:%u\n","profile_id", p_vprof_db->profile_id);
    SYS_DUMP_DB_LOG(p_file, "  %-20s:%x\n","data",  *((uint32*)&p_vprof_db->data));

    return CTC_E_NONE;
}
STATIC int32
_sys_usw_nexthop_fprintf_vxlan_edit_profile(uint8 lchip, uint8 idx, sal_file_t p_file, sys_nh_vxlan_hw_profile_t * p_node)
{
    if(p_node->ref_cnt == 0)
    {
        return CTC_E_NONE;
    }
    if(p_node->ref_cnt == 0xFFFFFF)
    {
        SYS_DUMP_DB_LOG(p_file, "%-20s:%-10u ref_cnt: static\n", "Profile idx",idx);
    }
    else
    {
        SYS_DUMP_DB_LOG(p_file, "%-20s:%-10u, ref_cnt:%u\n", "Profile idx",idx, p_node->ref_cnt);
    }
    SYS_DUMP_DB_LOG(p_file, "%-4s%-16s:%-10u\n", " ","UDP Dest Port",p_node->udp_dest_port);
    SYS_DUMP_DB_LOG(p_file, "%-4s%-16s:0x%x\n", " ","Vxlan Flags",p_node->flags);
    SYS_DUMP_DB_LOG(p_file, "%-4s%-16s:0x%x\n", " ","Vxlan rsv1",p_node->rsv1<<16|p_node->rsv2<<8|p_node->rsv3);
    SYS_DUMP_DB_LOG(p_file, "%-4s%-16s:0x%x\n", " ","Vxlan rsv2",p_node->rsv7);
    SYS_DUMP_DB_LOG(p_file, "%-4s%-16s:%u\n", " ","Rsv3 as Etype",p_node->rsv3_as_etype);
    SYS_DUMP_DB_LOG(p_file, "%-4s%-16s:%u\n", " ","Rsv3 as Protocol",p_node->rsv3_as_protocol);
    SYS_DUMP_DB_LOG(p_file, "%-4s%-16s:%u\n", " ","GBP enable",p_node->with_policy_group);
    SYS_DUMP_DB_LOG(p_file, "\n");

    return CTC_E_NONE;
}
STATIC int32
_sys_usw_nexthop_traverse_fprintf_pool(void* node, sys_dump_db_traverse_param_t* user_date)
{
    sal_file_t                  p_file      = (sal_file_t)user_date->value0;
    sys_nh_db_edit_t*           p_l2edit_db =  NULL;
    uint32*                     cnt         = (uint32 *)(user_date->value1);
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = user_date->lchip;
#endif
    p_l2edit_db = (sys_nh_db_edit_t*)((ctc_spool_node_t*)node)->data;
    SYS_DUMP_DB_LOG(p_file, "%-10s:%-5u,     %-10s:%-5u\n","Node", *cnt, "refcnt", ((ctc_spool_node_t*)node)->ref_cnt);
    SYS_DUMP_DB_LOG(p_file, "%-10s\n","----------------------------------------");
    SYS_DUMP_DB_LOG(p_file, "  %-20s:%u\n","edit_type", p_l2edit_db->edit_type);
    SYS_DUMP_DB_LOG(p_file, "  %-20s:%u\n","offset", p_l2edit_db->offset);
    (*cnt)++;
    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nexthop_traverse_fprintf_fp_pool(void* node, sys_dump_db_traverse_param_t* user_date)
{
    sal_file_t                  p_file      = (sal_file_t)user_date->value0;
    sys_nh_fp_prof_t*   p_db =  NULL;
    uint32*                     cnt         = (uint32 *)(user_date->value1);
    uint16 i = 0;
#ifdef CTC_SHELL_DEBUG_ON
    uint8 lchip = user_date->lchip;
#endif
    p_db = (sys_nh_fp_prof_t*)((ctc_spool_node_t*)node)->data;
    SYS_DUMP_DB_LOG(p_file, "%-10s:%-5u,     %-10s:%-5u\n","Node", *cnt, "refcnt", ((ctc_spool_node_t*)node)->ref_cnt);
    SYS_DUMP_DB_LOG(p_file, "%-10s\n","----------------------------------------");
    SYS_DUMP_DB_LOG(p_file, "  %-20s:%u\n","profile_id", p_db->profile_id);
    SYS_DUMP_DB_LOG(p_file, "  %-20s:%u\n","type", p_db->type);
    for (i = 0; i < SYS_NH_FP_DATA_NUM; i++)
    {
        SYS_DUMP_DB_LOG(p_file, "  %-20s:0x%x\n", "data", p_db->data[i]);
    }
    return CTC_E_NONE;
}

int32
sys_usw_nh_rsv_drop_ecmp_member(uint8 lchip)
{
    uint32 cmd = 0;
    DsEcmpMember_m  ecmp_mem;

    sal_memset(&ecmp_mem, 0, sizeof(DsEcmpMember_m));
    SetDsEcmpMember(V, array_0_dsFwdPtr_f, &ecmp_mem, 0);
    SetDsEcmpMember(V, array_1_dsFwdPtr_f, &ecmp_mem, 0);
    SetDsEcmpMember(V, array_2_dsFwdPtr_f, &ecmp_mem, 0);
    SetDsEcmpMember(V, array_3_dsFwdPtr_f, &ecmp_mem, 0);
    cmd = DRV_IOW(DsEcmpMember_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, 0, cmd, &ecmp_mem));

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_port_init(uint8 lchip, uint8 reverse)
{

    uint8 lchip_tmp                = 0;
    uint8 lchip_start              = 0;
    uint8 lchip_end                = 0;
    uint8  gchip                   = 0;
    uint32 gport                   = 0;
    uint32 index                   = 0;
    int32  ret                     = CTC_E_NONE;

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        return CTC_E_NONE;
    }

    lchip_tmp = lchip;
    sys_usw_get_gchip_id(lchip_tmp, &gchip);

    for (index = 0; index < MCHIP_CAP(SYS_CAP_PORT_NUM_PER_CHIP); lchip = lchip_tmp, index++)
    {
        gport = CTC_MAP_LPORT_TO_GPORT(gchip, SYS_MAP_DRV_LPORT_TO_SYS_LPORT(index));

        if (SYS_GPORT_IS_NETWORK_PORT(gport)||(SYS_DMPS_RSV_PORT == sys_usw_is_network_port(lchip, gport)))
        {
            /*init all chip port nexthop*/
            lchip = lchip_tmp;
            CTC_FOREACH_LCHIP(lchip_start, lchip_end, 1)
            {
                ret = reverse? sys_usw_brguc_nh_delete(lchip, gport): sys_usw_brguc_nh_create(lchip, gport, CTC_NH_PARAM_BRGUC_SUB_TYPE_ALL);
                if ((CTC_E_EXIST != ret) && (CTC_E_NONE != ret) && (CTC_E_NOT_INIT != ret))
                {
                    return ret;
                }
            }
        }
    }

   return CTC_E_NONE;
}

int32
_sys_usw_nexthop_dump_db(uint8 lchip, sal_file_t p_f, ctc_global_dump_db_t* p_dump_param)
{
    int32 ret = CTC_E_NONE;
    uint32 i = 0;
    sys_dump_db_traverse_param_t    cb_data;
    uint32 num_cnt = 0;

    SYS_DUMP_DB_LOG(p_f, "\n");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "#Nexthop");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "{");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "Master config:");
    SYS_DUMP_DB_LOG(p_f, "%s\n", "----------------------------------------------------------------------------------------------------------------------");
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max_external_nhid",      g_usw_nh_master[lchip]->max_external_nhid);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max_tunnel_id",          g_usw_nh_master[lchip]->max_tunnel_id);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max_srh_id",          g_usw_nh_master[lchip]->max_srh_id);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","ecmp_if_resolved_l2edit",g_usw_nh_master[lchip]->ecmp_if_resolved_l2edit);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","reflective_resolved_dsfwd_offset",g_usw_nh_master[lchip]->reflective_resolved_dsfwd_offset);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","fatal_excp_base",        g_usw_nh_master[lchip]->fatal_excp_base);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max_glb_nh_offset",      g_usw_nh_master[lchip]->max_glb_nh_offset);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max_glb_met_offset",      g_usw_nh_master[lchip]->max_glb_met_offset);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","ipmc_logic_replication",      g_usw_nh_master[lchip]->ipmc_logic_replication);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","pkt_nh_edit_mode",      g_usw_nh_master[lchip]->pkt_nh_edit_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max_ecmp",      g_usw_nh_master[lchip]->max_ecmp);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","max_ecmp_group_num",      g_usw_nh_master[lchip]->max_ecmp_group_num);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","cur_ecmp_cnt",      g_usw_nh_master[lchip]->cur_ecmp_cnt);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","reflective_brg_en",      g_usw_nh_master[lchip]->reflective_brg_en);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","rspan_vlan_id",      g_usw_nh_master[lchip]->rspan_vlan_id);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","met_mode",      g_usw_nh_master[lchip]->met_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","cid_use_4w",      g_usw_nh_master[lchip]->cid_use_4w);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","bpe_en",      g_usw_nh_master[lchip]->bpe_en);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","bpe mc en",      g_usw_nh_master[lchip]->bpe_mc_en);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","xlate_nh_offset",      g_usw_nh_master[lchip]->xlate_nh_offset);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","mpls_edit_offset",      g_usw_nh_master[lchip]->mpls_edit_offset);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","gem_port_edit_num",      g_usw_nh_master[lchip]->gem_port_edit_num);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","gem_port_edit_base",      g_usw_nh_master[lchip]->gem_port_edit_base);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","internal_nh_used_num",      g_usw_nh_master[lchip]->internal_nh_used_num);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","efd_nh_id",      g_usw_nh_master[lchip]->efd_nh_id);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","udf_profile_bitmap",      g_usw_nh_master[lchip]->udf_profile_bitmap);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","vxlan_mode",      g_usw_nh_master[lchip]->vxlan_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","hecmp_mem_num",      g_usw_nh_master[lchip]->hecmp_mem_num);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","h_ecmp_en",      g_usw_nh_master[lchip]->h_ecmp_en);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n", "ecmp_drop_mem_base[0]",      g_usw_nh_master[lchip]->ecmp_drop_mem_base[0]);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n", "ecmp_drop_mem_base[1]",      g_usw_nh_master[lchip]->ecmp_drop_mem_base[1]);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","rsv_iloop_nh",      g_usw_nh_master[lchip]->rsv_iloop_nh);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","outer_l2_ptr",      g_usw_nh_master[lchip]->outer_l2_ptr);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","outer_l2_ptr_ref",      g_usw_nh_master[lchip]->outer_l2_ptr_ref);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","mpls_spme_dis",      g_usw_nh_master[lchip]->mpls_spme_dis);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","rsv_l2edit_ptr",      g_usw_nh_master[lchip]->rsv_l2edit_ptr);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","rsv_l3edit_for_nsh",      g_usw_nh_master[lchip]->rsv_l3edit_for_nsh);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","external nh count",      g_usw_nh_master[lchip]->nhid_hash->count-g_usw_nh_master[lchip]->internal_nh_used_num);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","nh ext count",      g_usw_nh_master[lchip]->nhid_ext_hash->count);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","mpls tunnel count",      g_usw_nh_master[lchip]->tunnel_id_vec->used_cnt);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","mcast group count",      g_usw_nh_master[lchip]->mcast_group_vec->used_cnt);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","arp id used count",      g_usw_nh_master[lchip]->arp_id_hash->count);
    if (DRV_FROM_TMM(lchip))
    {
        SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","srh count",              g_usw_nh_master[lchip]->srh_id_hash->count);
        SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","fp used count",   g_usw_nh_master[lchip]->fp_id_hash->count);
    }
    if(DRV_FROM_TMM(lchip) || (DRV_IS_TSINGMA(lchip) && g_usw_nh_master[lchip]->bind_ldp))
    {
        SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","overlay tunnel count",   g_usw_nh_master[lchip]->ol_tunnel_hash->count);
    }
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","eloop nexthop count",   g_usw_nh_master[lchip]->eloop_list->count);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","logic replication count",   g_usw_nh_master[lchip]->repli_offset_list->count);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","met_ext_mode",      g_usw_nh_master[lchip]->met_ext_mode);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","nh_mapper_num",      g_usw_nh_master[lchip]->nh_mapper_num);
    SYS_DUMP_DB_LOG(p_f, "%-35s:%u\n","nh_mapper_base",      g_usw_nh_master[lchip]->nh_mapper_base);

    SYS_DUMP_DB_LOG(p_f, "%-35s:","udf_ether_type");
    for(i = 0; i < 4; i ++)
    {
        SYS_DUMP_DB_LOG(p_f, "[%u]",g_usw_nh_master[lchip]->udf_ether_type[i]);
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","udf_profile_ref_cnt");
    for(i = 0; i < 4; i ++)
    {
        SYS_DUMP_DB_LOG(p_f, "[%u]",g_usw_nh_master[lchip]->udf_profile_ref_cnt[i]);
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","nhid_used_cnt");
    for(i = 0; i < SYS_NH_TYPE_MAX; i ++)
    {
        SYS_DUMP_DB_LOG(p_f, "[%u]",g_usw_nh_master[lchip]->nhid_used_cnt[i]);
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","nhtbl_used_cnt");
    for(i = 0; i < SYS_NH_ENTRY_TYPE_MAX; i ++)
    {
        SYS_DUMP_DB_LOG(p_f, "[%u]",g_usw_nh_master[lchip]->nhtbl_used_cnt[i]);
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","cw_ref_cnt");
    for(i = 0; i < SYS_NH_CW_NUM; i ++)
    {
        SYS_DUMP_DB_LOG(p_f, "[%u]",g_usw_nh_master[lchip]->cw_ref_cnt[i]);
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","sys_nh_resolved_offset");
    for(i = 0; i < SYS_NH_RES_OFFSET_TYPE_MAX; i ++)
    {
        SYS_DUMP_DB_LOG(p_f, "[%4u,%4u,%4u]",g_usw_nh_master[lchip]->sys_nh_resolved_offset[i].offset_base,
            g_usw_nh_master[lchip]->sys_nh_resolved_offset[i].entry_size, g_usw_nh_master[lchip]->sys_nh_resolved_offset[i].entry_num);
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","nh_table_info_array");
    for(i = 0; i < SYS_NH_ENTRY_TYPE_MAX; i ++)
    {
        SYS_DUMP_DB_LOG(p_f, "[%4u,%4u,%4u,%4u,%4u]",g_usw_nh_master[lchip]->nh_table_info_array[i].table_id, g_usw_nh_master[lchip]->nh_table_info_array[i].entry_size,
            g_usw_nh_master[lchip]->nh_table_info_array[i].opf_pool_type, g_usw_nh_master[lchip]->nh_table_info_array[i].alloc_dir,
            g_usw_nh_master[lchip]->nh_table_info_array[i].table_8w);
        if ((((i+1)%6) == 0))
        {
            SYS_DUMP_DB_LOG(p_f, "\n");
            SYS_DUMP_DB_LOG(p_f, "%-35s:","");
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","ipmc_dsnh_offset");
    for(i = 0; i < MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM); i ++)
    {
        if (!g_usw_nh_master[lchip]->ipmc_dsnh_offset[i])
        {
            continue;
        }
        SYS_DUMP_DB_LOG(p_f, "[%u:%u]", i, g_usw_nh_master[lchip]->ipmc_dsnh_offset[i]);
        if ((((i+1)%48) == 0))
        {
            SYS_DUMP_DB_LOG(p_f, "\n");
            SYS_DUMP_DB_LOG(p_f, "%-35s:","");
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","pon_ipmc_dsnh_offset");
    for(i = 0; i < MCHIP_CAP(SYS_CAP_SPEC_L3IF_NUM); i ++)
    {
        if (!g_usw_nh_master[lchip]->pon_ipmc_dsnh_offset[i])
        {
            continue;
        }
        SYS_DUMP_DB_LOG(p_f, "[%u:%u]", i, g_usw_nh_master[lchip]->pon_ipmc_dsnh_offset[i]);
        if ((((i+1)%48) == 0))
        {
            SYS_DUMP_DB_LOG(p_f, "\n");
            SYS_DUMP_DB_LOG(p_f, "%-35s:","");
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","ipv4 ipsa");
    for(i = 0; i < MCHIP_CAP(SYS_CAP_NH_IP_TUNNEL_IPV4_IPSA_NUM); i ++)
    {
        sys_nh_ip_tunnel_sa_v4_node_t* p_node = NULL;
        uint32 tempip = 0;
        char ip[100] = {0};

        p_node = (sys_nh_ip_tunnel_sa_v4_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_4] + i;
        if (!p_node->count)
        {
            continue;
        }
        tempip = sal_ntohl(p_node->ipv4);
        sal_inet_ntop(AF_INET, &tempip, ip, CTC_IPV6_ADDR_STR_LEN);
        SYS_DUMP_DB_LOG(p_f, "[%u:%u, %s]",i, p_node->count, ip);
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    SYS_DUMP_DB_LOG(p_f, "%-35s:","ipv6 ipsa");
    for(i = 0; i < MCHIP_CAP(SYS_CAP_NH_IP_TUNNEL_IPV6_IPSA_NUM); i ++)
    {
        sys_nh_ip_tunnel_sa_v6_node_t* p_node = NULL;
        char ip[100] = {0};
        ipv6_addr_t sw_ipv6_address;
        p_node = (sys_nh_ip_tunnel_sa_v6_node_t*)g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_6] + i;
        if (!p_node->count)
        {
            continue;
        }

        sw_ipv6_address[0] = sal_ntohl(p_node->ipv6[0]);
        sw_ipv6_address[1] = sal_ntohl(p_node->ipv6[1]);
        sw_ipv6_address[2] = sal_ntohl(p_node->ipv6[2]);
        sw_ipv6_address[3] = sal_ntohl(p_node->ipv6[3]);
        sal_inet_ntop(AF_INET6, sw_ipv6_address, ip, CTC_IPV6_ADDR_STR_LEN);
        SYS_DUMP_DB_LOG(p_f, "[%u:%u, %s]",i, p_node->count, ip);
        if (((i+1)%6) == 0)
        {
            SYS_DUMP_DB_LOG(p_f, "\n");
            SYS_DUMP_DB_LOG(p_f, "%-35s:","");
        }
    }
    SYS_DUMP_DB_LOG(p_f, "\n");

    sys_usw_opf_fprint_alloc_used_info(lchip, g_usw_nh_master[lchip]->nh_opf_type, p_f);
    sys_usw_opf_fprint_alloc_used_info(lchip, g_usw_nh_master[lchip]->ecmp_group_opf_type, p_f);
    sys_usw_opf_fprint_alloc_used_info(lchip, g_usw_nh_master[lchip]->ecmp_member_opf_type, p_f);
    sys_usw_opf_fprint_alloc_used_info(lchip, g_usw_nh_master[lchip]->vxlan_opf_type_inner_fid, p_f);
    if (DRV_FROM_TMM(lchip))
    {
        sys_usw_opf_fprint_alloc_used_info(lchip, g_usw_nh_master[lchip]->fp_opf_type, p_f);
    }
    sal_memset(&cb_data, 0, sizeof(sys_dump_db_traverse_param_t));
    cb_data.value0 = p_f;
    cb_data.value1 = &num_cnt;
    cb_data.lchip = lchip;
    SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","p_edit_spool");
    ctc_spool_traverse(g_usw_nh_master[lchip]->p_edit_spool, (spool_traversal_fn)_sys_usw_nexthop_traverse_fprintf_pool , (void*)(&cb_data));

    sal_memset(&cb_data, 0, sizeof(sys_dump_db_traverse_param_t));
    num_cnt = 0;
    cb_data.value0 = p_f;
    cb_data.value1 = &num_cnt;
    cb_data.lchip = lchip;
    SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","p_l2edit_vprof(DsOfEditVlanActionProfile_t)");
    ctc_spool_traverse(g_usw_nh_master[lchip]->p_l2edit_vprof, (spool_traversal_fn)_sys_usw_nexthop_traverse_fprintf_vprof_pool, (void*)(&cb_data));

    sal_memset(&cb_data, 0, sizeof(sys_dump_db_traverse_param_t));
    num_cnt = 0;
    cb_data.value0 = p_f;
    cb_data.value1 = &num_cnt;
    cb_data.lchip = lchip;
    SYS_DUMP_DB_LOG(p_f, "Spool type: %s\n","p_fp_spool");
    ctc_spool_traverse(g_usw_nh_master[lchip]->p_fp_spool, (spool_traversal_fn)_sys_usw_nexthop_traverse_fprintf_fp_pool, (void*)(&cb_data));

    /*dump vxlan edit profile*/
    if(DRV_FROM_TM(lchip))
    {
        SYS_DUMP_DB_LOG(p_f, "\nVxlan Edit Profile(EpePktProcVxlanRsvCtl)\n");
        SYS_DUMP_DB_LOG(p_f, "%s\n","-----------------------------------------");
        for(i=0; i < SYS_NH_MAX_VXLAN_PROFLLE; i++)
        {
            _sys_usw_nexthop_fprintf_vxlan_edit_profile(lchip, i, p_f, &g_usw_nh_master[lchip]->vxlan_edit_profile[i]);
        }
        SYS_DUMP_DB_LOG(p_f, "%s\n","-----------------------------------------\n");
    }

    /*dump eloop list*/
    if(p_dump_param->detail && g_usw_nh_master[lchip]->eloop_list->count)
    {
        ctc_slistnode_t* slist_node = NULL;
        sys_nh_eloop_node_t *p_eloop_node = NULL;

        SYS_DUMP_DB_LOG(p_f, "%-35s\n", "Eloop nexthop list:");
        SYS_DUMP_DB_LOG(p_f, "%-10s%-10s%-12s%-10s\n","nhid","edit ptr","is_l2_edit","ref cnt");
        SYS_DUMP_DB_LOG(p_f, "------------------------------------------\n");
        CTC_SLIST_LOOP(g_usw_nh_master[lchip]->eloop_list, slist_node)
        {
            p_eloop_node = _ctc_container_of(slist_node, sys_nh_eloop_node_t, head);
            SYS_DUMP_DB_LOG(p_f, "%-10u%-10u%-12s%-10u\n", p_eloop_node->nhid, p_eloop_node->edit_ptr, p_eloop_node->is_l2edit?"Y":"N", p_eloop_node->ref_cnt);
        }
        SYS_DUMP_DB_LOG(p_f, "------------------------------------------\n");
    }
    SYS_DUMP_DB_LOG(p_f, "%s\n", "}");
    return ret;
}

int32
sys_usw_nh_init(uint8 lchip, ctc_nh_global_cfg_t* nh_cfg)
{
    uint32 entry_num = 0;
    sys_usw_nh_master_t* p_master = NULL;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);
	LCHIP_CHECK(lchip);
    /*Nexthop module have initialize*/
    if (NULL != g_usw_nh_master[lchip])
    {
        return CTC_E_NONE;
    }

    if (nh_cfg->max_external_nhid == 0)
    {
        nh_cfg->max_external_nhid = SYS_NH_EXTERNAL_NHID_DEFAUL_NUM;
    }

    if (nh_cfg->max_tunnel_id == 0)
    {
        nh_cfg->max_tunnel_id = SYS_NH_TUNNEL_ID_DEFAUL_NUM;
    }
    if (nh_cfg->max_srh_id == 0)
    {
        nh_cfg->max_srh_id = SYS_NH_SRH_ID_DEFAUL_NUM;
    }

    /*1. Create master*/
    CTC_ERROR_RETURN(_sys_usw_nh_master_new(lchip, &p_master, nh_cfg->max_external_nhid, nh_cfg->max_tunnel_id,
                                                                                                                 SYS_NH_ARP_ID_DEFAUL_NUM, nh_cfg->max_srh_id));
    g_usw_nh_master[lchip] = p_master;
    g_usw_nh_master[lchip]->max_external_nhid = nh_cfg->max_external_nhid;
    g_usw_nh_master[lchip]->max_tunnel_id = nh_cfg->max_tunnel_id;
    g_usw_nh_master[lchip]->max_srh_id = nh_cfg->max_srh_id;
    g_usw_nh_master[lchip]->mpls_spme_dis = DRV_FROM_TMM(lchip)?nh_cfg->mpls_spme_dis:0;

    if (nh_cfg->nh_edit_mode == CTC_NH_EDIT_MODE_SINGLE_CHIP)
    {
        g_usw_nh_master[lchip]->pkt_nh_edit_mode = SYS_NH_EDIT_MODE_IGS;
    }
    else if(nh_cfg->nh_edit_mode == 2)
    {
        g_usw_nh_master[lchip]->pkt_nh_edit_mode  = SYS_NH_EDIT_MODE_USER_DEF ;
    }
    else if(nh_cfg->nh_edit_mode == CTC_NH_EDIT_MODE_MULTI_CHIP)
    {
        g_usw_nh_master[lchip]->pkt_nh_edit_mode  = SYS_NH_EDIT_MODE_MISC ;
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    g_usw_nh_master[lchip]->h_ecmp_en = (DRV_IS_TSINGMA(lchip)&&(SYS_GET_CHIP_VERSION != SYS_CHIP_SUB_VERSION_A)) ? 1 :nh_cfg->h_ecmp_en;

    SYS_USW_NH_MAX_ECMP_CHECK(nh_cfg->max_ecmp);
    g_usw_nh_master[lchip]->max_ecmp  = (nh_cfg->max_ecmp > MCHIP_CAP(SYS_CAP_NH_MAX_ECPN))?MCHIP_CAP(SYS_CAP_NH_MAX_ECPN) :nh_cfg->max_ecmp;
    if (0 == nh_cfg->max_ecmp)
    {
        g_usw_nh_master[lchip]->max_ecmp_group_num = MCHIP_CAP(SYS_CAP_NH_ECMP_GROUP_ID_NUM);
    }
    else
    {
        g_usw_nh_master[lchip]->max_ecmp_group_num = (MCHIP_CAP(SYS_CAP_NH_ECMP_MEMBER_NUM) / nh_cfg->max_ecmp) - 1;
        if ( g_usw_nh_master[lchip]->max_ecmp_group_num > MCHIP_CAP(SYS_CAP_NH_ECMP_GROUP_ID_NUM))
        {
            g_usw_nh_master[lchip]->max_ecmp_group_num = MCHIP_CAP(SYS_CAP_NH_ECMP_GROUP_ID_NUM);
        }
    }

    g_usw_nh_master[lchip]->reflective_brg_en = 0;
    g_usw_nh_master[lchip]->ipmc_logic_replication = 0;
    g_usw_nh_master[lchip]->met_mode = 0;
    g_usw_nh_master[lchip]->cid_use_4w = 1;
    g_usw_nh_master[lchip]->ldp_mac_profile_en = 0;


    /*2. Install Semantic callback*/
    if (CTC_E_NONE != _sys_usw_nh_callback_init(lchip, g_usw_nh_master[lchip]))
    {
        mem_free( g_usw_nh_master[lchip]);
        g_usw_nh_master[lchip] = NULL;
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;
    }

    if (CTC_E_NONE != sys_usw_nh_table_info_init(lchip))
    {
        mem_free( g_usw_nh_master[lchip]);
        g_usw_nh_master[lchip] = NULL;
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;

    }

    /*3. Offset  init*/
    if (CTC_E_NONE != _sys_usw_nh_offset_init(lchip, p_master, nh_cfg))
    {
        mem_free( g_usw_nh_master[lchip]);
        g_usw_nh_master[lchip] = NULL;
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;

    }

    /*4. global cfg init*/
    if (CTC_E_NONE != sys_usw_nh_global_cfg_init(lchip))
    {
        mem_free( g_usw_nh_master[lchip]);
        g_usw_nh_master[lchip] = NULL;
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;

    }

    if (CTC_E_NONE != sys_usw_nh_misc_init(lchip))
    {
        mem_free(g_usw_nh_master[lchip]);
        g_usw_nh_master[lchip] = NULL;
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;

    }

    if (MCHIP_NH(lchip)->fp_init)
    {
        if (CTC_E_NONE != MCHIP_NH(lchip)->fp_init(lchip))
        {
            mem_free(g_usw_nh_master[lchip]);
            g_usw_nh_master[lchip] = NULL;
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
            return CTC_E_NOT_INIT;

        }
    }

    if (MCHIP_NH(lchip)->nsh_init)
    {
        if (CTC_E_NONE != MCHIP_NH(lchip)->nsh_init(lchip, FALSE))
        {
            mem_free(g_usw_nh_master[lchip]);
            g_usw_nh_master[lchip] = NULL;
            SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
            return CTC_E_NOT_INIT;
        }
    }

    CTC_ERROR_RETURN(sys_usw_rpf_init(lchip));


    /* dump-db register */
    CTC_ERROR_RETURN(sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_NEXTHOP, sys_usw_nexthop_dump_db));
    CTC_ERROR_RETURN(sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MAX,sys_usw_nh_wb_sync));

    if (DRV_IS_DUET2(lchip) || DRV_IS_TSINGMA(lchip))
    {
        g_usw_nh_master[lchip]->vxlan_mode = 0;
    }
    else if(DRV_FROM_TMM(lchip))
    {
        g_usw_nh_master[lchip]->vxlan_mode = 1;
    }

    if (CTC_WB_ENABLE(lchip) && CTC_WB_STATUS(lchip) == CTC_WB_STATUS_RELOADING)
    {
        CTC_ERROR_RETURN(sys_usw_nh_wb_restore(lchip));
    }
    if (CTC_WB_ENABLE(lchip))
    {
        CTC_ERROR_RETURN(_sys_usw_nh_wb_init(lchip));
    }
    /* set chip_capability */
    MCHIP_CAP(SYS_CAP_SPEC_ECMP_GROUP_NUM) = g_usw_nh_master[lchip]->max_ecmp_group_num + 1;
    MCHIP_CAP(SYS_CAP_SPEC_ECMP_MEMBER_NUM) = g_usw_nh_master[lchip]->max_ecmp;
    MCHIP_CAP(SYS_CAP_SPEC_EXTERNAL_NEXTHOP_NUM) = g_usw_nh_master[lchip]->max_external_nhid;
    MCHIP_CAP(SYS_CAP_SPEC_GLOBAL_DSNH_NUM) = g_usw_nh_master[lchip]->max_glb_nh_offset;
    MCHIP_CAP(SYS_CAP_SPEC_MPLS_TUNNEL_NUM) = g_usw_nh_master[lchip]->max_tunnel_id;
    if (DRV_FROM_TMM(lchip))
    {
        sys_usw_ftm_query_table_entry_num(lchip, DsEcmpDlbFlowStateLeft_t, &entry_num);
    }
    else
    {
        sys_usw_ftm_query_table_entry_num(lchip, DsDlbFlowStateLeft_t, &entry_num);
    }
    MCHIP_CAP(SYS_CAP_SPEC_ECMP_DLB_FLOW_NUM) = entry_num;

    if (CTC_E_NONE != _sys_usw_nh_port_init(lchip, FALSE))
    {
        _sys_usw_nh_port_init(lchip, TRUE);
        mem_free( g_usw_nh_master[lchip]);
        g_usw_nh_master[lchip] = NULL;
        SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " Feature not initialized \n");
        return CTC_E_NOT_INIT;
    }

    return CTC_E_NONE;
}

#define ___________deinit___________
STATIC int32
_sys_usw_nh_free_node_data(void* node_data, void* user_data)
{
    uint8 lchip = 0;
    sys_nh_info_com_t* p_nhinfo = NULL;
    sys_nh_info_ext_t* p_nhinfo_ext = NULL;
    sys_nh_info_mcast_t* p_mcast = NULL;
    sys_nh_info_ipuc_t* p_ipuc = NULL;
    sys_nh_info_ecmp_t* p_ecmp = NULL;
    sys_nh_info_mpls_t* p_mpls = NULL;
    sys_nh_db_srh_t*    p_srh = NULL;
    ctc_list_pointer_node_t* p_pos, * p_pos_next;
    sys_nh_mcast_meminfo_t* p_member;
    sys_traverse_t* p_param;
    sys_nh_ref_oam_node_t* p_ref_oam_list = NULL;
    void* pd = NULL;
    sys_nh_info_bind_t* bind_data = NULL;

    if (user_data)
    {
        p_param = (sys_traverse_t*)user_data;
        lchip = p_param->value1;
        if (p_param->value2 == SYS_NH_DB_TYPE_NH_INFO)
        {
            p_nhinfo=(sys_nh_info_com_t*)node_data;
            switch(p_nhinfo->hdr.nh_entry_type)
            {
                case SYS_NH_TYPE_MCAST:
                    p_mcast = (sys_nh_info_mcast_t*)(p_nhinfo);
                    CTC_LIST_POINTER_LOOP_DEL(p_pos, p_pos_next, &(p_mcast->p_mem_list))
                    {
                        p_member = _ctc_container_of(p_pos, sys_nh_mcast_meminfo_t, list_head);
                        if (!DRV_FROM_TMM(lchip) && p_member->dsmet.vid_list)
                        {
                            mem_free(p_member->dsmet.vid_list);
                        }
                        else if (CTC_FLAG_ISSET(p_member->dsmet.flag, SYS_NH_DSMET_FLAG_LOGIC_REPLI_EN))
                        {
                            ctc_list_pointer_node_t* p_logic_pos, * p_logic_next;
                            sys_nh_mcast_meminfo_t* logic_rep_node = NULL;
                            CTC_LIST_POINTER_LOOP_DEL(p_logic_pos, p_logic_next, &p_member->dsmet.logic_rep_list)
                            {
                                logic_rep_node = _ctc_container_of(p_logic_pos, sys_nh_mcast_meminfo_t, list_head);
                                sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_LOGIC_REP, 1, logic_rep_node->dsmet.dsmet_offset);
                                /*delete node from logic replicate list*/
                                ctc_list_pointer_delete(&p_member->dsmet.logic_rep_list, &(p_member->list_head));
                                mem_free(logic_rep_node);
                            }
                        }
                        mem_free(p_member);
                    }
                    break;
                case SYS_NH_TYPE_IPUC:
                    p_ipuc = (sys_nh_info_ipuc_t*)(p_nhinfo);
                    pd = p_ipuc->pd;
                    if(!pd)
                    {
                        break;
                    }
                    p_ref_oam_list = ((sys_nh_info_ipuc_pdata_t*)pd)->oam_list;
                    bind_data = ((sys_nh_info_ipuc_pdata_t*)pd)->bind_data;
                    break;
                case SYS_NH_TYPE_ECMP:
                    p_ecmp = (sys_nh_info_ecmp_t*)(p_nhinfo);
                    if (p_ecmp->nh_array)
                    {
                        mem_free(p_ecmp->nh_array);
                    }
                    break;
                case SYS_NH_TYPE_MPLS:
                    p_mpls = (sys_nh_info_mpls_t*)(p_nhinfo);
                    pd = p_mpls->pd;
                    if(!pd)
                    {
                        break;
                    }
                    p_ref_oam_list = ((sys_nh_info_mpls_pdata_t*)pd)->oam_list;
                    bind_data = ((sys_nh_info_mpls_pdata_t*)pd)->bind_data;
                    break;
                case SYS_NH_TYPE_IP_TUNNEL:
                    bind_data = ((sys_nh_info_ip_tunnel_t*)(p_nhinfo))->bind_data;
                    break;
                case SYS_NH_TYPE_WLAN_TUNNEL:
                    break;
                case SYS_NH_TYPE_SRV6:
                    bind_data = ((sys_nh_info_srv6_t*)(p_nhinfo))->bind_data;
                    break;
                case SYS_NH_TYPE_TRILL:
                    bind_data = ((sys_nh_info_trill_t*)(p_nhinfo))->bind_data;
                /*p_dsl2edit resource release in l2edithash free, here skip*/
                    break;
                case SYS_NH_TYPE_MISC:
                    bind_data = ((sys_nh_info_misc_t*)(p_nhinfo))->bind_data;
                    break;
                case SYS_NH_TYPE_APS:
                    bind_data = ((sys_nh_info_aps_t*)(p_nhinfo))->bind_data;
                    break;

                default:
                    break;
            }

            if (p_ref_oam_list)
            {
                sys_nh_ref_oam_node_t* p_ref_node, * p_tmp_node;
                p_ref_node = p_ref_oam_list;
                while (p_ref_node)
                {
                    /*Remove from db*/
                    p_tmp_node = p_ref_node;
                    p_ref_node = p_ref_node->p_next;
                    mem_free(p_tmp_node);
                }
            }
            if (bind_data)
            {
                mem_free(bind_data);
            }
            if (pd)
            {
                mem_free(pd);
            }
        }
        else if(p_param->value2 == SYS_NH_DB_TYPE_NH_INFO_EXT)
        {

            p_nhinfo_ext = (sys_nh_info_ext_t*)node_data;

            if (p_nhinfo_ext->ecmp_list)
            {
                sys_nh_ref_list_node_t* p_ref_node, * p_tmp_node;
                p_ref_node = p_nhinfo_ext->ecmp_list;
                while (p_ref_node)
                {
                    /*Remove from db*/
                    p_tmp_node = p_ref_node;
                    p_ref_node = p_ref_node->p_next;
                    mem_free(p_tmp_node);
                }
            }
            if (p_nhinfo_ext->aps_list)
            {
                sys_nh_ref_list_node_t* p_ref_node, * p_tmp_node;
                p_ref_node = p_nhinfo_ext->aps_list;
                while (p_ref_node)
                {
                    /*Remove from db*/
                    p_tmp_node = p_ref_node;
                    p_ref_node = p_ref_node->p_next;
                    mem_free(p_tmp_node);
                }
            }

        }
        else if (p_param->value2 == SYS_NH_DB_TYPE_ARP)
        {
            /*process arp db*/
            sys_nh_db_arp_t*  p_arp = NULL;
            ctc_list_pointer_node_t* p_pos, * p_pos_next;
            sys_nh_db_arp_nh_node_t* p_arp_nh_node = NULL;

            p_arp=(sys_nh_db_arp_t*)node_data;
            if (p_arp->pd->nh_list)
            {
                CTC_LIST_POINTER_LOOP_DEL(p_pos, p_pos_next, p_arp->pd->nh_list)
                {
                    p_arp_nh_node = _ctc_container_of(p_pos, sys_nh_db_arp_nh_node_t, head);
                    mem_free(p_arp_nh_node);
                }
                mem_free(p_arp->pd->nh_list);
            }
            mem_free(p_arp->pd);
        }
        else if (p_param->value2 == SYS_NH_DB_TYPE_MPLS_TNL)
        {
            /*process mpls tunnel*/
            sys_nh_db_mpls_tunnel_t* p_tunnel = NULL;
            sys_nh_ref_list_node_t* p_ref_node;
            sys_nh_ref_list_node_t* p_tmp_node;
            sys_nh_tunnel_ref_list_node_t* p_tunnel_node;
            sys_nh_tunnel_ref_list_node_t* p_tunnel_tmp;

            p_tunnel = (sys_nh_db_mpls_tunnel_t*)node_data;
            if(p_tunnel->pd->sr)  mem_free(p_tunnel->pd->sr);
            p_ref_node = p_tunnel->pd->p_ref_nh_list;
            while (p_ref_node)
            {
                /*Remove from db*/
                p_tmp_node = p_ref_node;
                p_ref_node = p_ref_node->p_next;
                mem_free(p_tmp_node);
            }

            p_tunnel_node = p_tunnel->pd->p_tunnel_list;
            while (p_tunnel_node)
            {
                /*Remove from db*/
                p_tunnel_tmp = p_tunnel_node;
                p_tunnel_node = p_tunnel_node->p_next;
                mem_free(p_tunnel_tmp);
            }
            mem_free(p_tunnel->pd);

        }
        else if (p_param->value2 == SYS_NH_DB_TYPE_OVERLAY_TNL)
        {
            /*process vxlan tunnel*/
            sys_nh_db_ol_tunnel_t* p_tunnel = NULL;
            sys_nh_ref_list_node_t* p_ref_node;
            sys_nh_ref_list_node_t* p_tmp_node;

            p_tunnel = (sys_nh_db_ol_tunnel_t*)node_data;
            p_ref_node = p_tunnel->p_ref_nh_list;
            while (p_ref_node)
            {
                /*Remove from db*/
                p_tmp_node = p_ref_node;
                p_ref_node = p_ref_node->p_next;
                mem_free(p_tmp_node);
            }
        }
        else if (p_param->value2 == SYS_NH_DB_TYPE_SRH)
        {
            sys_nh_ref_list_node_t* p_temp = NULL;
            sys_nh_ref_list_node_t* p_ref_srv6_list = NULL;
            sys_nh_tunnel_ref_list_node_t* p_tunnel_node;
            sys_nh_tunnel_ref_list_node_t* p_tunnel_tmp;
            p_srh = (sys_nh_db_srh_t*)(node_data);
            p_ref_srv6_list = p_srh->pd->nh_list;
            while (p_ref_srv6_list)
            {
                p_temp = p_ref_srv6_list;
                p_ref_srv6_list = p_ref_srv6_list->p_next;
                mem_free(p_temp);
            }

            p_tunnel_node = p_srh->pd->p_srh_list;
            while (p_tunnel_node)
            {
                /*Remove from db*/
                p_tunnel_tmp = p_tunnel_node;
                p_tunnel_node = p_tunnel_node->p_next;
                mem_free(p_tunnel_tmp);
            }
            mem_free(p_srh->pd);
        }
    }
    mem_free(node_data);

    return CTC_E_NONE;
}

int32
sys_usw_nh_deinit(uint8 lchip)
{
    ctc_slistnode_t* pnode = NULL;
    struct ctc_slistnode_s*  pnext   = NULL;
    sys_nh_eloop_node_t *p_eloop_node = NULL;
    sys_nh_repli_offset_node_t *p_offset_node = NULL;
    sys_traverse_t param;

    LCHIP_CHECK(lchip);
    if (NULL == g_usw_nh_master[lchip])
    {
        return CTC_E_NONE;
    }

    if(g_usw_nh_master[lchip]->vxlan_edit_profile)
    {
        mem_free(g_usw_nh_master[lchip]->vxlan_edit_profile);
    }
    sal_memset(&param, 0, sizeof(sys_traverse_t));
    param.value1 = lchip;
    param.value2 = SYS_NH_DB_TYPE_NH_INFO;
    /*free internal nhid vector*/
    ctc_hash_free2(g_usw_nh_master[lchip]->nhid_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, &param);
    param.value2 = SYS_NH_DB_TYPE_NH_INFO_EXT;
    ctc_hash_free2(g_usw_nh_master[lchip]->nhid_ext_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, &param);

    /*free tunnel id vector*/
    param.value2 = SYS_NH_DB_TYPE_MPLS_TNL;
    ctc_vector_traverse(g_usw_nh_master[lchip]->tunnel_id_vec, (vector_traversal_fn)_sys_usw_nh_free_node_data, &param);
    ctc_vector_release(g_usw_nh_master[lchip]->tunnel_id_vec);

    /*free mcast group nhid vector*/
    /*mcast vec data have freed in free nh info, here just free vec*/
    ctc_vector_release(g_usw_nh_master[lchip]->mcast_group_vec);

    param.value2 = SYS_NH_DB_TYPE_SRH;
    /*free srh id hash*/
    ctc_hash_free2(g_usw_nh_master[lchip]->srh_id_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, &param);

    /*free arp id hash*/
    param.value2 = SYS_NH_DB_TYPE_ARP;
    ctc_hash_free2(g_usw_nh_master[lchip]->arp_id_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, &param);

    /*free vp hash*/
    param.value2 = SYS_NH_DB_TYPE_OVERLAY_TNL;
    ctc_hash_free2(g_usw_nh_master[lchip]->ol_tunnel_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, &param);
    ctc_hash_free2(g_usw_nh_master[lchip]->nh_offset_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, NULL);
    /*free fp hash*/
    ctc_hash_free2(g_usw_nh_master[lchip]->fp_id_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, NULL);
    /*free vxlan hash*/
    ctc_hash_free2(g_usw_nh_master[lchip]->vxlan_vni_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, NULL);

    ctc_spool_free(g_usw_nh_master[lchip]->p_fp_spool);
    /*free l2edit data*/
    ctc_spool_free(g_usw_nh_master[lchip]->p_edit_spool);
    ctc_spool_free(g_usw_nh_master[lchip]->p_l2edit_vprof);

    /*free Eloop list*/
    CTC_SLIST_LOOP_DEL(g_usw_nh_master[lchip]->eloop_list, pnode, pnext)
    {
        p_eloop_node = _ctc_container_of(pnode, sys_nh_eloop_node_t, head);
        mem_free(p_eloop_node);
    }
    ctc_slist_free(g_usw_nh_master[lchip]->eloop_list);

    if (g_usw_nh_master[lchip]->repli_offset_list)
    {
        /*free logic rep list*/
        CTC_SLIST_LOOP_DEL(g_usw_nh_master[lchip]->repli_offset_list, pnode, pnext)
        {
            p_offset_node = _ctc_container_of(pnode, sys_nh_repli_offset_node_t, head);
            mem_free(p_offset_node);
        }
        ctc_slist_free(g_usw_nh_master[lchip]->repli_offset_list);
    }

    mem_free(g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_4]);
    mem_free(g_usw_nh_master[lchip]->ipsa[CTC_IP_VER_6]);
    mem_free(g_usw_nh_master[lchip]->p_occupid_nh_offset_bmp);
    if (g_usw_nh_master[lchip]->max_glb_met_offset)
    {
        mem_free(g_usw_nh_master[lchip]->p_occupid_met_offset_bmp);
    }


    /*free opf resource*/
    sys_usw_opf_deinit(lchip, g_usw_nh_master[lchip]->ecmp_group_opf_type);
    sys_usw_opf_deinit(lchip, g_usw_nh_master[lchip]->ecmp_member_opf_type);
    sys_usw_opf_deinit(lchip, g_usw_nh_master[lchip]->nh_opf_type);
    sys_usw_opf_deinit(lchip, g_usw_nh_master[lchip]->vxlan_opf_type_inner_fid);

    if (DRV_FROM_TMM(lchip))
    {
        sys_usw_opf_deinit(lchip, g_usw_nh_master[lchip]->fp_opf_type);
    }

    sys_usw_dump_db_register_cb(lchip, CTC_FEATURE_NEXTHOP, NULL);
    sys_usw_wb_sync_register_cb(lchip, CTC_FEATURE_NEXTHOP,0, NULL);
    mem_free(g_usw_nh_master[lchip]->ipmc_dsnh_offset);
    mem_free(g_usw_nh_master[lchip]->pon_ipmc_dsnh_offset);
    if (MCHIP_NH(lchip)->nsh_init)
    {
        MCHIP_NH(lchip)->nsh_init(lchip, TRUE);
    }
    mem_free(g_usw_nh_master[lchip]);

    sys_usw_rpf_deinit(lchip);

    return CTC_E_NONE;
}

#define ___________XGPON___________

int32
sys_usw_nh_update_logic_port(uint8 lchip, uint32 nhid, uint32 logic_port)
{
    uint32 dsnh_offset = 0;
    sys_nh_info_com_t*p_nhinfo = NULL;
    sys_nexthop_t dsnh_8w;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo));
    if (NULL == p_nhinfo)
    {
        return CTC_E_NH_INVALID_NHID;
    }

    if (!CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_USE_DSNH8W))
    {
        return CTC_E_NOT_SUPPORT;
    }

    dsnh_offset = p_nhinfo->hdr.dsnh_offset;

    CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, dsnh_offset, &dsnh_8w));

    dsnh_8w.logic_dest_port = logic_port;

    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, dsnh_offset, &dsnh_8w));


    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_xgpon_reserve_mpls_edit(uint8 lchip)
{
    uint16 i = 0;
    uint32 offset_base = 0;
    sys_dsmpls_t  dsmpls;

    LCHIP_CHECK(lchip);

    CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS, 8192, &offset_base));
    g_usw_nh_master[lchip]->mpls_edit_offset = offset_base;

    sal_memset(&dsmpls, 0, sizeof(sys_dsmpls_t));

    dsmpls.l3_rewrite_type = 1;
    dsmpls.ttl_index = 1;
    dsmpls.exp = 1;
    dsmpls.map_ttl_mode = 1;
    dsmpls.map_ttl = 1;
    for (i=0; i<8192; i++)
    {
        dsmpls.label = i+1;
        CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS, offset_base+i, &dsmpls));
    }

    return CTC_E_NONE;
}

STATIC int32
_sys_usw_nh_xgpon_reserve_vlan_edit(uint8 lchip)
{
    uint16 i = 0;
    uint32 offset_base = 0;
    sys_nh_param_dsnh_t dsnh_param;
    ctc_vlan_egress_edit_info_t vlan_edit_info;

    LCHIP_CHECK(lchip);

    CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 4096, &offset_base));
    g_usw_nh_master[lchip]->xlate_nh_offset = offset_base;

    sal_memset(&dsnh_param, 0, sizeof(dsnh_param));
    dsnh_param.dest_vlan_ptr = SYS_DSNH_DESTVLANPTR_SPECIAL;
    dsnh_param.dsnh_type = SYS_NH_PARAM_DSNH_TYPE_BRGUC;

    sal_memset(&vlan_edit_info, 0, sizeof(vlan_edit_info));
    vlan_edit_info.svlan_edit_type = CTC_VLAN_EGRESS_EDIT_INSERT_VLAN;
    vlan_edit_info.cvlan_edit_type = CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE;
    CTC_SET_FLAG(vlan_edit_info.edit_flag, CTC_VLAN_EGRESS_EDIT_OUPUT_SVID_VALID);
    CTC_SET_FLAG(vlan_edit_info.edit_flag, CTC_VLAN_EGRESS_EDIT_REPLACE_SVLAN_COS);
    CTC_SET_FLAG(vlan_edit_info.flag, CTC_VLAN_NH_ETREE_LEAF);
    vlan_edit_info.stag_cos = 0;

    dsnh_param.p_vlan_info = &vlan_edit_info;

    for (i=0; i<4096; i++)
    {
        vlan_edit_info.output_svid = i;
        dsnh_param.dsnh_offset = offset_base+i;
        CTC_ERROR_RETURN(sys_usw_nh_write_entry_dsnh4w(lchip, &dsnh_param));
    }

    return CTC_E_NONE;
}

int32
sys_usw_nh_is_logic_repli_en(uint8 lchip, uint32 nhid, uint8 *is_repli_en)
{
    sys_nh_info_com_t* p_nhinfo = NULL;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, nhid, &p_nhinfo));
    *is_repli_en = CTC_FLAG_ISSET(p_nhinfo->hdr.nh_entry_flags, SYS_NH_INFO_FLAG_LOGIC_REPLI_EN);

    return CTC_E_NONE;
}

extern int32
sys_usw_port_set_isolation_mode(uint8 lchip, uint8 choice_mode);
extern int32
sys_usw_nh_set_reflective_brg_en(uint8 lchip, uint8 enable);
int32
sys_usw_nh_set_xgpon_en(uint8 lchip, uint8 enable, uint32 flag)
{
    uint32 field_val = 0;
    uint32 cmd = 0;
    sys_usw_nh_master_t* p_nh_master = g_usw_nh_master[lchip];

    LCHIP_CHECK(lchip);

    /*rsv group 0 for common group*/
    if (enable)
    {
        CTC_BIT_UNSET(p_nh_master->p_occupid_met_offset_bmp[0], 0);
        field_val = 1;
        if (DRV_IS_DUET2(lchip)&& (!CTC_FLAG_ISSET(flag, 1<<1)))
        {
            CTC_ERROR_RETURN(_sys_usw_nh_xgpon_reserve_vlan_edit(lchip));
        }
        if (DRV_IS_DUET2(lchip))
        {
            CTC_ERROR_RETURN(_sys_usw_nh_xgpon_reserve_mpls_edit(lchip));
        }
        else if (flag && (0 == p_nh_master->gem_port_edit_num))/*flag means gem_port_num*/
        {
            uint32 offset = 0;
            CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_FLEX_8W, flag >> 3, &offset));
            p_nh_master->gem_port_edit_base = offset;
            p_nh_master->gem_port_edit_num = flag >> 3;
        }
        sys_usw_port_api_set_isolation_mode(lchip, 1);
    }
    else
    {
        CTC_BIT_SET(p_nh_master->p_occupid_met_offset_bmp[0], 0);
        field_val = 0;
        CTC_ERROR_RETURN(sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_4W, 4096, p_nh_master->xlate_nh_offset));
        if (DRV_IS_DUET2(lchip))
        {
            CTC_ERROR_RETURN(sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_L3EDIT_MPLS, 8192, p_nh_master->mpls_edit_offset));
        }
        else if (p_nh_master->gem_port_edit_num)
        {
            sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_FLEX_8W, p_nh_master->gem_port_edit_num, p_nh_master->gem_port_edit_base);
            p_nh_master->gem_port_edit_num = 0;
        }
    }
    sys_usw_nh_set_reflective_brg_en(lchip, enable);
    cmd = DRV_IOW(EpeHeaderEditCtl_t, EpeHeaderEditCtl_loopbackUseSourcePort_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    return CTC_E_NONE;
}

int32
sys_usw_nh_set_mcast_bitmap_ptr(uint8 lchip, uint32 offset)
{
    uint32 field_val = 0;
    uint32 cmd = 0;

    LCHIP_CHECK(lchip);

    field_val = g_usw_nh_master[lchip]->xlate_nh_offset + offset;
    cmd = DRV_IOW(MetFifoCtl_t, MetFifoCtl_portBitmapNextHopPtr_f);
    CTC_ERROR_RETURN(DRV_FIELD_IOCTL(lchip, 0, cmd, &field_val));

    return CTC_E_NONE;
}

 /*DsL2EditFlex for gem port*/
 int32
_sys_usw_nh_add_gem_port_l2edit_8w_outer(uint8 lchip, uint16 logic_dest_port, uint16 gem_vlan)
{
    uint32 offset = 0;
    sys_dsl2edit_eth_t dsl2edit;

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_FUNC, "%s()\n", __FUNCTION__);

    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "add gem port logic_dest:%d ,gem_port %d!!\n",
                   logic_dest_port, gem_vlan);
    offset = SYS_NH_GEMPORT_MAP(logic_dest_port);
    SYS_NH_DBG_OUT(CTC_DEBUG_LEVEL_INFO, "l2edit offset=%d\n", offset);
    sal_memset(&dsl2edit, 0, sizeof(dsl2edit));
    dsl2edit.ds_type  = SYS_NH_DS_TYPE_L2EDIT;
    if (DRV_FROM_TMM(lchip))
    {
        dsl2edit.l2_rewrite_type  = DRV_ENUM(DRV_L2EDITTYPE_RWETH2X);
    }
    else
    {
        dsl2edit.l2_rewrite_type  = SYS_NH_L2EDIT_TYPE_FLEX_8W;
    }
    dsl2edit.offset = offset;
    /* The output_vlan_id and output_vid represent the gem_vlan*/
    dsl2edit.output_vid = gem_vlan;
    /* The output_vlan_is_svlan and dynamic represent the logic_dest_port*/
    dsl2edit.ether_type = logic_dest_port;
    CTC_ERROR_RETURN(sys_usw_nh_write_asic_table(lchip, SYS_NH_ENTRY_TYPE_L2EDIT_FLEX_8W, offset, &dsl2edit));
    return CTC_E_NONE;
}
int32
sys_usw_nh_add_gem_port_l2edit_8w_outer(uint8 lchip, uint16 logic_dest_port, uint16 gem_vlan)
{
    CTC_ERROR_RETURN(_sys_usw_nh_add_gem_port_l2edit_8w_outer(lchip, logic_dest_port, gem_vlan));
    return CTC_E_NONE;
}

int32
sys_usw_nh_remove_gem_port_l2edit_8w_outer(uint8 lchip, uint16 logic_dest_port)
{
    CTC_ERROR_RETURN(_sys_usw_nh_add_gem_port_l2edit_8w_outer(lchip, logic_dest_port, 0));
    return CTC_E_NONE;
}

uint32
sys_usw_nh_get_gem_port_l2edit_8w_outer_index(uint8 lchip, uint16 logic_dest_port)
{
    return SYS_NH_GEMPORT_MAP(logic_dest_port);
}

uint8
sys_usw_nh_is_xgpon_hybrid(uint8 lchip, uint32 logic_port)
{

    if (DRV_IS_TMM(lchip)
        && g_usw_nh_master[lchip]->gem_port_edit_num
        && logic_port
        && (logic_port < (g_usw_nh_master[lchip]->gem_port_edit_num << 3)))
    {
        return TRUE;
    }
    return FALSE;
}

int32
sys_usw_nh_get_xgpon_flooding_dsnh(uint8 lchip, uint32 logic_port, uint32* p_dsnh_offset, uint8* p_use_dsnh8w)
{
    DsNextHop8W_m dsnh_8w;
    uint8 index = 0;
    uint8 is_find = 0;

    for(index=0; index<SYS_NH_PON_MC_DSNH_NUM; index++)
    {
        if (0 != g_usw_nh_master[lchip]->pon_mc_dsnh[index])
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, g_usw_nh_master[lchip]->pon_mc_dsnh[index], &dsnh_8w));
            if (logic_port == GetDsNextHop8W(V, logicDestPort_f,  &dsnh_8w))
            {
                is_find = 1;
                break;
            }
        }
    }

    if (0 == is_find)
    {
        return CTC_E_NOT_EXIST;
    }

    *p_dsnh_offset = g_usw_nh_master[lchip]->pon_mc_dsnh[index];
    *p_use_dsnh8w = 1;

    return CTC_E_NONE;
}

int32
sys_usw_nh_xgpon_flooding_en(uint8 lchip, uint32 logic_port, uint8 enable)
{
    sys_nh_param_dsnh_t dsnh_param;
    ctc_vlan_egress_edit_info_t vlan_info;
    DsNextHop8W_m dsnh_8w;
    uint8 index = 0;
    uint8 is_find = 0;
    uint8 unused_index = 0;
    int32 ret = CTC_E_NONE;

    unused_index = SYS_NH_PON_MC_DSNH_NUM;
    for(index=0; index<SYS_NH_PON_MC_DSNH_NUM; index++)
    {
        if (0 == g_usw_nh_master[lchip]->pon_mc_dsnh[index])
        {
            unused_index = index;
        }
        else
        {
            CTC_ERROR_RETURN(sys_usw_nh_get_asic_table(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, g_usw_nh_master[lchip]->pon_mc_dsnh[index], &dsnh_8w));
            if (logic_port == GetDsNextHop8W(V, logicDestPort_f,  &dsnh_8w))
            {
                is_find = 1;
                break;
            }
        }
    }

    if ((1 == enable) &&(SYS_NH_PON_MC_DSNH_NUM == unused_index) && (0 == is_find))
    {
        return CTC_E_NO_RESOURCE;
    }

    if ((1 == enable) && (0 == is_find))
    {
        sal_memset(&dsnh_param, 0, sizeof(sys_nh_param_dsnh_t));
        sal_memset(&vlan_info, 0, sizeof(ctc_vlan_egress_edit_info_t));
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER, 1);

        dsnh_param.dsnh_type = SYS_NH_PARAM_DSNH_TYPE_BRGUC;
        dsnh_param.l2edit_ptr = SYS_NH_GEMPORT_MAP(logic_port);
        dsnh_param.logic_port = logic_port;
        dsnh_param.p_vlan_info = &vlan_info;
        vlan_info.svlan_edit_type = CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE;
        vlan_info.cvlan_edit_type = CTC_VLAN_EGRESS_EDIT_KEEP_VLAN_UNCHANGE;
        CTC_ERROR_RETURN(sys_usw_nh_offset_alloc(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, 1,
                                                        &dsnh_param.dsnh_offset));

        CTC_ERROR_GOTO(sys_usw_nh_write_entry_dsnh8w(lchip, &dsnh_param), ret, roll_back_0);
        g_usw_nh_master[lchip]->pon_mc_dsnh[unused_index] = dsnh_param.dsnh_offset;
    }
    else if ((0 == enable) && (1 == is_find))
    {
        SYS_USW_REGISTER_WB_SYNC_EN(lchip, CTC_FEATURE_NEXTHOP, SYS_WB_APPID_NH_SUBID_MASTER, 1);
        sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, 1,
                                                        g_usw_nh_master[lchip]->pon_mc_dsnh[index]);
        sal_memset(&dsnh_param, 0, sizeof(sys_nh_param_dsnh_t));
        sys_usw_nh_write_entry_dsnh8w(lchip, &dsnh_param);
        g_usw_nh_master[lchip]->pon_mc_dsnh[index] = 0;
    }

    return CTC_E_NONE;

roll_back_0:
    sys_usw_nh_offset_free(lchip, SYS_NH_ENTRY_TYPE_NEXTHOP_8W, 1, dsnh_param.dsnh_offset);
    return ret;
}

#define ___________OTHER___________

int32
sys_usw_nh_ecmp_get_lb_hash_mem(uint8 lchip, uint32 ecmp_nh_id, uint16 hash_value, uint32 * p_nh_id)
{
    uint32 cmd = 0;
    DsEcmpGroup_m ecmp_grp;
    sys_nh_info_ecmp_t* p_nhdb = NULL;
    uint32 mem_num = 0;
    uint16 ecmp_hash_val = 0;
    uint8 cost_path_sel = 0;

    CTC_ERROR_RETURN(sys_usw_nh_get_nhinfo_by_nhid(lchip, ecmp_nh_id, (sys_nh_info_com_t**)&p_nhdb));
    if ((SYS_NH_TYPE_ECMP != p_nhdb->hdr.nh_entry_type)
       || (CTC_NH_ECMP_TYPE_STATIC != p_nhdb->type)
       || (0 == p_nhdb->valid_cnt))
    {
        return CTC_E_INVALID_PARAM;
    }
    cmd = DRV_IOR(DsEcmpGroup_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DRV_IOCTL(lchip, p_nhdb->ecmp_group_id, cmd, &ecmp_grp));
    mem_num = GetDsEcmpGroup(V, memberNum_f, &ecmp_grp);
    if(!CTC_IS_BIT_SET(mem_num, 7))
    {
        ecmp_hash_val = hash_value&0xFF;
        cost_path_sel = ecmp_hash_val % ((mem_num&0x7F) + 1);
    }
    else
    {
        ecmp_hash_val = hash_value;
        if (mem_num&0x7)
        {
            cost_path_sel = hash_value & ((1 << ((mem_num&0x7)+7))-1);
        }
    }
    *p_nh_id = p_nhdb->nh_array[cost_path_sel%(p_nhdb->valid_cnt)];

    return CTC_E_NONE;
}
int32
sys_usw_nh_bind_ldp_en(uint8 lchip, uint8 enable)
{
    if (!DRV_IS_TSINGMA(lchip))
    {
        return CTC_E_NOT_SUPPORT;
    }
	
    if (g_usw_nh_master[lchip]->bind_ldp==0 && enable)
    {
        CTC_ERROR_RETURN(_sys_usw_nh_vp_tunnel_init(lchip, g_usw_nh_master[lchip]));
    }
	else if(g_usw_nh_master[lchip]->bind_ldp && !enable)
    {
        sys_traverse_t param;   
        sal_memset(&param, 0, sizeof(sys_traverse_t));
        /*free vp hash*/
        param.value2 = SYS_NH_DB_TYPE_OVERLAY_TNL;
        ctc_hash_free2(g_usw_nh_master[lchip]->ol_tunnel_hash, (hash_traversal_fn)_sys_usw_nh_free_node_data, &param);
		g_usw_nh_master[lchip]->ol_tunnel_hash = NULL;
    }
	g_usw_nh_master[lchip]->bind_ldp = enable;
	
    return CTC_E_NONE;
}

